SQL za vrazka na tri tablitzi

6 отговора 274 прегледа
#1

SQL za vrazka na tri tablitzi

stava duma za Postgres. Iskam da vsema kato rezultat spisak saz zapisite v edna tablitza i broia na saotvetstvashtite v drugi dve s neshto ot roda:

SELECT count(ALL contacts.contact_id) AS count_contacts, count(ALL users.user_id) AS count_users, offices.office_id, offices.office_name FROM contacts, users, offices WHERE offices.office_id=users.office_id AND offices.office_id=contacts.office_id GROUP BY offices.office_id, offices.office_name

obache mi vrashta neveren rezultat. vrashta 4 kontakta (kolkoto i usera), vapreki che e samo edin, i estestveno, ne mi pokazva officite v koito niama useri ili kontakti.

Probvah s razni INNER JOIN, no resultata e sashtia, ne moga da izmislia nishto, a mi se shte da go napravia s edin SQL, a ne s dva.

Niakvi idei?

Отговор
в отговор на gonzales #2

Re: SQL za vrazka na tri tablitzi

parvata stapka e napravena - dava mi veren broi na useri i kontakti:

SELECT users.count_users, contacts.count_contacts, offices.office_id, offices.office_name FROM offices, (SELECT count(users.user_id) AS count_users, users.office_id AS u_office FROM users GROUP BY office_id) AS users, (SELECT count(contacts.contact_id) AS count_contacts, contacts.office_id AS c_office FROM contacts GROUP BY office_id) AS contacts WHERE offices.office_id=users.u_office AND offices.office_id=contacts.c_office

malko e slozno, ama...

Отговор
в отговор на gonzales #3

Re: SQL za vrazka na tri tablitzi

Именно :)
Сложно е и при това не само за теб но и за сървъра.
Винаги котато можеш една заявка да я напишеш с join и sub-select е по-добре да предпочетеш join

> Probvah s razni INNER JOIN, no resultata e sashtia..

Естествено защото това е същия join просто алтернативен синтаксис

from a, b where a.id=b.id
е еквивалентно на
from a inner join b on a.id = b.id

Аз предпочитам запетайката

Дай малко детайли обаче, защото нещо не схващам идеята.
И да опростим примерчето пък ти после ще си го препишеш.

users (id, o_id)
office (id)
contacts (id, o_id)

Това ли ти е структурата в опростен вариант?

Каква е крайната ти цел?
Брой на какво?

GROUP BY offices.office_id, offices.office_name

на това не му схващам смисъла - отношението office_id <-> office_name не е ли 1 към ?

Та какво всъщност искаш като бройка?
Напиши го на човешки език:
- За всеки Офис брой на ....

Linux is like a wigwam - No Windows, No Gates, Apache inside
Отговор
в отговор на salle #4

Re: SQL za vrazka na tri tablitzi

mii da, po printzip otnoshenieto e po u_id, no v sluchaia az iskam da dam spisak s officite, kato za vseki ofice dam broia contacti i useri, taka che otnoshenieto stava o_id.

users (u_id, o_id)
office (o_id)
contacts (u_id, o_id)

no ako iskame savsem da go oprostim, v parvo priblizenie neka vzemem 2 tablitzi - iskame spisak ot ednata s broia korespondirashti ot drugata:

SELECT offices.*, count(users.u_id) FROM offices, users WHERE offices.o_id=users.o_id;

obache tazi zaiavka ne mi vrashta officite, za koito count()=0. a az bih iskal da gi pokaze :-(((

Отговор
в отговор на gonzales #5

Re: SQL za vrazka na tri tablitzi

Я пак, че нещо не разбрах:

mysql> create table offices (id int unsigned auto_increment primary key, name char(16));

mysql> insert into offices (name) values('Един Офис'), ('Друг Офис');

mysql> select * from offices;
+----+-----------+
| id | name |
+----+-----------+
| 1 | Един Офис |
| 2 | Друг Офис |
+----+-----------+


mysql> create table users (id int unsigned auto_increment primary key, o_id int unsigned, name char(8), key(o_id));

mysql> insert into users (name, o_id) values('Гошо', 1), ('Пешо', 1);

mysql> select * from users;
+----+------+------+
| id | o_id | name |
+----+------+------+
| 1 | 1 | Гошо |
| 2 | 1 | Пешо |
+----+------+------+


Сега твойта заявка (с INNER JOIN):

SELECT offices.*, count(users.id) FROM offices, users WHERE offices.id=users.o_id group by offices.id;
+----+-----------+----------+
| id | name | count(*) |
+----+-----------+----------+
| 1 | Един Офис | 2 |
+----+-----------+----------+

Което вече ти е известно.

Ха да пробвамe с LEFT JOIN:

mysql> SELECT offices.*, count(users.id) FROM offices LEFT JOIN users ON offices.id=users.o_id group by offices.id;
+----+-----------+-----------------+
| id | name | count(users.id) |
+----+-----------+-----------------+
| 1 | Един Офис | 2 |
| 2 | Друг Офис | 0 |
+----+-----------+-----------------+

За което всащност си мечтаеш нали така

А това е защото:
mysql> SELECT offices.*, users.* FROM offices LEFT JOIN users ON offices.id=users.o_id;
+----+-----------+------+------+------+
| id | name | id | o_id | name |
+----+-----------+------+------+------+
| 1 | Един Офис | 1 | 1 | Гошо |
| 1 | Един Офис | 2 | 1 | Пешо |
| 2 | Друг Офис | NULL | NULL | NULL |
+----+-----------+------+------+------+


Забележи NULL в "Дясната" таблица. Които NULLs могат да се използват във WHERE клаузата.

Тъй, че примерно прословутия SUB-SELECT
SELECT * FROM offices WHERE offices.id NOT IN (SELECT o_id FROM users);

Може (и е доста по-ефективно) да се изпълни като

SELECT * FROM offices LEFT JOIN users ON offices.id = users.o_id WHERE users.o_id IS NULL;

mysql> SELECT offices.* FROM offices LEFT JOIN users ON offices.id = users.o_id WHERE users.o_id IS NULL;
+----+-----------+
| id | name |
+----+-----------+
| 2 | Друг Офис |
+----+-----------+




Други проблеми да имаш?

Linux is like a wigwam - No Windows, No Gates, Apache inside
Отговор
в отговор на salle #6

Re: SQL za vrazka na tri tablitzi

TZAR SI :-)))

sega ostava da go shvana po-dobre tzialoto tova, no tova e po-lesnoto!

Отговор
в отговор на salle #7

Re: SQL za vrazka na tri tablitzi

veche i az sam tzar! poluchi se nuznia efect, sega veche sam shtastliv, che nauchih neshto novo!

SELECT contacts.*, countries.country_name AS country, company_types.type_name AS company_type FROM contacts LEFT JOIN company_types ON contacts.company_type_id=company_types.type_id LEFT JOIN countries ON contacts.country_id=countries.country_id WHERE contact_id=10

Отговор