Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Którego zapytania użyć?, Dla znacznej puli wyników?
darko
post
Post #1





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Witam mam następujące dwie tabele:

tabela klienci
  1. CREATE TABLE `customers` (
  2. `id_customers` int(11) NOT NULL AUTO_INCREMENT,
  3. `id_advisors` int(11) NOT NULL DEFAULT '1',
  4. `id_consulting_companies` int(11) NOT NULL,
  5. `id_managers` int(11) NOT NULL,
  6. `id_users` int(11) NOT NULL,
  7. `name` varchar(55) NOT NULL,
  8. `surname` varchar(60) NOT NULL,
  9. `address_street` varchar(255) NOT NULL,
  10. `address_city` varchar(255) NOT NULL,
  11. `address_postal` varchar(7) NOT NULL,
  12. `phone` varchar(15) NOT NULL,
  13. `mobile` varchar(12) NOT NULL,
  14. `email` varchar(55) NOT NULL,
  15. `notes` text,
  16. `status` tinyint(1) NOT NULL DEFAULT '1',
  17. PRIMARY KEY (`id_customers`),
  18. KEY `fk_adv` (`id_advisors`),
  19. KEY `fk_consult_cmpny` (`id_consulting_companies`),
  20. KEY `fk_usr3` (`id_users`),
  21. KEY `fk_mana` (`id_managers`),
  22. CONSTRAINT `fk_adv` FOREIGN KEY (`id_advisors`) REFERENCES `advisors` (`id_advisors`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  23. CONSTRAINT `fk_consult_cmpny` FOREIGN KEY (`id_consulting_companies`) REFERENCES `consulting_companies` (`id_consulting_companies`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  24. CONSTRAINT `fk_mana` FOREIGN KEY (`id_managers`) REFERENCES `managers` (`id_managers`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  25. CONSTRAINT `fk_usr3` FOREIGN KEY (`id_users`) REFERENCES `users` (`id_users`) ON DELETE NO ACTION ON UPDATE NO ACTION
  26. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8


oraz tabela testy klientów

  1. CREATE TABLE `customers_tests` (
  2. `id_customers_tests` int(11) NOT NULL AUTO_INCREMENT,
  3. `id_customers` int(11) NOT NULL DEFAULT '1' ,
  4. `id_tests_versions` int(11) NOT NULL DEFAULT '1' ,
  5. `result` int(11) NOT NULL DEFAULT '1',
  6. `profile` tinyint(1) DEFAULT NULL,
  7. `test_date` datetime DEFAULT NULL,
  8. `notes` text,
  9. `status` tinyint(1) NOT NULL,
  10. PRIMARY KEY (`id_customers_tests`),
  11. KEY `fk_customer` (`id_customers`),
  12. KEY `fk_tv` (`id_tests_versions`),
  13. CONSTRAINT `fk_customer` FOREIGN KEY (`id_customers`) REFERENCES `customers` (`id_customers`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  14. CONSTRAINT `fk_tv` FOREIGN KEY (`id_tests_versions`) REFERENCES `tests_versions` (`id_tests_versions`) ON DELETE NO ACTION ON UPDATE NO ACTION
  15. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8


I mam trzy zapytania wyciągające dane zawarte w tabeli klienci, ale nie mające równoważnych rekordów w drugiej tabeli testy. Oto te zapytania:
1)
  1. SELECT *
  2. FROM customers
  3. WHERE NOT EXISTS (SELECT * FROM customers_tests WHERE customers.id_customers = customers_tests.id_customers)

2)
  1. SELECT * FROM customers c, customers_tests t WHERE c.id_customers <> t.id_customers

oraz 3)
  1. SELECT * FROM customers
  2. LEFT JOIN customers_tests ON customers.id_customers = customers_tests.id_customers
  3. WHERE customers_tests.id_customers IS NULL


I teraz pytanie: zakładając, że będzie bardzo dużo (setki tysięcy) rekordów spełniających warunek: rekord w tabeli podstawowej, ale brak w tej drugiej, którego zapytania użyć najlepiej? Nie mam tylu danych, żeby sprawdzić i porobić testy. W sumie zależy mi na odpowiedzi co do zasady, jak postępować w takich sytuacjach.
ps. silnik InnoDB; select version() zwraca: Mysql 5.0.51a-24+lenny2+spu1
Pozdrawiam.
darko


--------------------
Nie pomagam na pw, tylko forum.
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 6)
erix
post
Post #2





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Cytat
Nie mam tylu danych, żeby sprawdzić i porobić testy.

A nie możesz ich wygenerować? winksmiley.jpg


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
Mchl
post
Post #3





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

Ostrzeżenie: (0%)
-----


1) Podzapytanie skorelowane, czyli coś czego chcemy unikać
2) To w ogóle daje Ci takie wyniki jak chcesz?
Go to the top of the page
+Quote Post
darko
post
Post #4





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Dzięki za odpowiedzi. Odnośnie tworzenia mega zbioru rekordów na potrzeby testów - ok jak tylko znajdę chwilę - zrobię testy porównując czasy. Jaka pula rekordów byłaby miarodajna? Generalnie chodzi mi o to co jest bardziej wydajne w poleceniach select: operacje na indeksach czy korzystanie z joinów?
~Mchl - 1) skreślam z listy. 2) tak, wszystkie 3 zapytania zwracają poprawne dane.


--------------------
Nie pomagam na pw, tylko forum.
Go to the top of the page
+Quote Post
Mchl
post
Post #5





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

Ostrzeżenie: (0%)
-----


Ad 2) Moim zdaniem mylisz się, albo nie rozumiem co chcesz uzyskać.

Jeżeli będziesz miał w tabeli customers rekordy o id_customers 1,2,3,4 a w tabeli customers_test rekordy o id_customers 2, 4 to w wyniku tego zapytania dostaniesz:

Kod
c.id_customers, t.id_customers
1,2
1,4
2,4
3,2
3,4
4,2
Go to the top of the page
+Quote Post
darko
post
Post #6





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


blinksmiley.gif Faktycznie smile.gif Umknęło mi to.


--------------------
Nie pomagam na pw, tylko forum.
Go to the top of the page
+Quote Post
puc
post
Post #7





Grupa: Zarejestrowani
Postów: 32
Pomógł: 2
Dołączył: 4.12.2004

Ostrzeżenie: (0%)
-----


najszybszy powinien być left join (rozwiązanie 3)
  1. SELECT * FROM customers
  2. LEFT JOIN customers_tests ON customers.id_customers = customers_tests.id_customers
  3. WHERE customers_tests.id_customers IS NULL


kiedyś testowałem i jest to naprawdę wydajne. przy czym jeżeli zależy ci bardzo na wydajności to zrezygnuj z * na rzecz wylistowania ręcznego kolumn
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 22.08.2025 - 00:58