Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Którego zapytania użyć?
Forum PHP.pl > Forum > Bazy danych > MySQL
darko
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
erix
Cytat
Nie mam tylu danych, żeby sprawdzić i porobić testy.

A nie możesz ich wygenerować? winksmiley.jpg
Mchl
1) Podzapytanie skorelowane, czyli coś czego chcemy unikać
2) To w ogóle daje Ci takie wyniki jak chcesz?
darko
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.
Mchl
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
darko
blinksmiley.gif Faktycznie smile.gif Umknęło mi to.
puc
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
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.