• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

SELECT COUNT(tab1), COUNT(tab2), ... Problem ze złączeniem trzech tabel

VPS Starter Arubacloud
0 głosów
1,279 wizyt
pytanie zadane 6 października 2015 w SQL, bazy danych przez Janusz92 Bywalec (2,150 p.)

Zapewne popełniam oczywisty dla wielu błąd, ale jakoś nie mogę się przez to przebić...

Chodzi o to aby z trzech tabel wybrać różne rekordy, przy czym z dwóch tabel chcę tylko zliczyć odpowiednie. Zapytanie które stworzyłem zwraca chyba iloczyn kartezjański dla COUNT'ów. (Gdy robię COUNT tylko dla jednej dodatkowej tabeli po JOIN to działa jak należy)

Aktualne zapytanie:

SELECT COUNT(i.img_id) as ile_postow, COUNT(c.com_id) as ile_komentarzy, user, register, last 
FROM users u
JOIN images i ON i.author=u.id
JOIN comments c ON c.author=u.id
WHERE u.id=1

Struktura tabel:

CREATE TABLE IF NOT EXISTS `comments` (
  `com_id` int(11) NOT NULL AUTO_INCREMENT,
  `author` int(11) NOT NULL,
  `post` int(11) NOT NULL,
  `com` varchar(2048) NOT NULL,
  `date` datetime NOT NULL,
  PRIMARY KEY (`com_id`),
  KEY `author` (`author`),
  KEY `post` (`post`)
)

CREATE TABLE IF NOT EXISTS `images` (
  `img_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(256) NOT NULL,
  `title` varchar(32) NOT NULL,
  `descr` varchar(64) NOT NULL,
  `datetime` datetime NOT NULL,
  `onmain` datetime NOT NULL,
  `author` int(11) NOT NULL,
  `main` tinyint(1) NOT NULL,
  PRIMARY KEY (`img_id`),
  KEY `author` (`author`)
) 

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` varchar(16) NOT NULL,
  `pass` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `register` datetime NOT NULL,
  `last` datetime DEFAULT NULL,
  `isAdmin` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`)
)

3 odpowiedzi

+1 głos
odpowiedź 6 października 2015 przez jeremus Maniak (59,720 p.)

chcesz wylistowac userow, oraz informacje o ilości postów i komentarzy oraz datę rejestracji i logowania ?

niestety wychodzi Ci iloczyn kartezjański

1. albo dwa zapytania 

2. albo jedno np. takie

with pom as ( SELECT COUNT(i.img_id) as ile_postow, user, register, last,u.id as id  FROM users u JOIN images i ON i.author=u.id  WHERE u.id=1 )

select p.*, COUNT(c.com_id) as ile_komentarzy from pom p  JOIN comments c ON c.author=p.id

 -- jesli robisz to w mysql'u to tu chyba nie ma clausuli with ( może jest coś podobnego ), jak nie to jakies subquery

komentarz 6 października 2015 przez Janusz92 Bywalec (2,150 p.)

Tak, a w zasadzie to jednego usera.

Na ten moment zapytanie z podzapytaniem ułożyłem w ten sposób.

SELECT COUNT(img_id) as ile_postow, (SELECT COUNT(com_id) FROM comments WHERE author=1) AS ile_kom, user, register, last FROM users INNER JOIN images ON id=author WHERE id=1

Wynik takiego zapytania to:

ile_postow ile_kom user register last
219 25 Admin 2015-08-30 12:00:00 2015-10-02 11:40:46

Gdzie 219 i 25 to faktyczne liczby. W nieprawidłowym zapytaniu wychodziło 219*25.

Myślę jednak, że ta się to jakoś zrobić samymi joinami. Może później na świeżo mi coś do głowy przyjdzie.

komentarz 7 października 2015 przez jeremus Maniak (59,720 p.)
i bardzo ładnie Ci wyszło, prawdopodobnie tez będzie wydajniejsze niż łączenie trzech tabel

ten select jako subquery wykonuje się tylko raz  - tak przynajmniej powinien działać motor bazy danych

chyba nie da się bez podzapytania, zawsze wyjdzie Ci iloczyn kartezjański, jedyne co mi przychodzi do głowy to zastąpienie count() czymś sprytniejszym.. ( iif , case itp ,  oraz (group by ) tak aby  nie powielać liczenia rekordów )
0 głosów
odpowiedź 6 października 2015 przez ScriptyChris Mędrzec (190,190 p.)
Z tego co zdążyłem liznąć SQLa, to nie ma czegoś takiego jak po prostu JOIN "

JOIN images i ON i.author=u.id

JOIN comments c ON c.author=u.id"

Musisz określić czy to będzie left/right/inner/outer JOIN, tak po prostu JOIN raczej być nie może. Nawet edytor Ci tego JOINa nie wyróżnił innym kolorem.
komentarz 6 października 2015 przez mowmiheniek Stary wyjadacz (11,900 p.)
Mylisz się. JOIN oznacza INNER JOIN. Ale dla przejrzystości zalecane jest stosowanie INNER JOIN.
komentarz 6 października 2015 przez ScriptyChris Mędrzec (190,190 p.)
Ok, a dlaczego edytor nie oznaczył tego JOIN odpowiednio (tak jak SELECT, ON, WHERE i pozostałe elementy SQL'a) w powyższym kodzie?
komentarz 6 października 2015 przez mowmiheniek Stary wyjadacz (11,900 p.)
Ale mu wyrzuca jakiś wynik, a nie błąd składni. Czemu nie oznaczył tego to nie wiem.
0 głosów
odpowiedź 6 października 2015 przez mowmiheniek Stary wyjadacz (11,900 p.)
Nie wiem czy to pomoże ale user to zastrzerzone słowo w MySQL, użyj to tak: `user`

Podobne pytania

0 głosów
2 odpowiedzi 201 wizyt
pytanie zadane 11 czerwca 2017 w SQL, bazy danych przez glocek2121 Nowicjusz (160 p.)
0 głosów
1 odpowiedź 271 wizyt
pytanie zadane 11 maja 2018 w PHP przez Browarnik123 Użytkownik (830 p.)
0 głosów
1 odpowiedź 781 wizyt
pytanie zadane 20 października 2016 w SQL, bazy danych przez Bartess Gaduła (3,630 p.)

93,081 zapytań

142,045 odpowiedzi

321,464 komentarzy

62,427 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...