SQL za vrazka na tri tablitzi
6 отговора
274 прегледа
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?
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?
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...
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...
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
Сложно е и при това не само за теб но и за сървъра.
Винаги котато можеш една заявка да я напишеш с 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
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 :-(((
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 :-(((
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
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
Re: SQL za vrazka na tri tablitzi
TZAR SI :-)))
sega ostava da go shvana po-dobre tzialoto tova, no tova e po-lesnoto!
sega ostava da go shvana po-dobre tzialoto tova, no tova e po-lesnoto!
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
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