• 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,035 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 180 wizyt
pytanie zadane 11 czerwca 2017 w SQL, bazy danych przez glocek2121 Nowicjusz (160 p.)
0 głosów
1 odpowiedź 227 wizyt
pytanie zadane 11 maja 2018 w PHP przez Browarnik123 Użytkownik (830 p.)
0 głosów
1 odpowiedź 665 wizyt
pytanie zadane 20 października 2016 w SQL, bazy danych przez Bartess Gaduła (3,630 p.)

92,452 zapytań

141,262 odpowiedzi

319,074 komentarzy

61,854 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.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...