"обратното" на join
9 отговора
0 прегледа
"обратното" на join
Здравейте.
Представете си две таблици, свързани в съотношение 1:n - в едната има id и някакви данни, а в другата ключ към първата и нейните си данни; във втората няколко реда могат да имат един и същ външен ключ.
Питането е следното: как да вземем тези редове от първата таблица, към които няма ключ във втората?
Сещам се за един начин, но ми се струва неразумен от гледна точка на производителност:
Предполагам, че решението е очевидно, но не се сещам. Идеи?
Представете си две таблици, свързани в съотношение 1:n - в едната има id и някакви данни, а в другата ключ към първата и нейните си данни; във втората няколко реда могат да имат един и същ външен ключ.
Питането е следното: как да вземем тези редове от първата таблица, към които няма ключ във втората?
Сещам се за един начин, но ми се струва неразумен от гледна точка на производителност:
select distinct a.* from a, b where a.id != b.a_fkey
Предполагам, че решението е очевидно, но не се сещам. Идеи?
Re: "обратното" на join
-- old-school за single column keys
select a.*
from a
where a.pk not in (select a_fkey from b)
-- old-scool за composite keys
select a.*
from a
where not exists (select *
from b
where b.a_fkey = a.pk)
-- neo-gamei
select a.*
from a
left join b
on a.pk = b.a_fkey
where b.pk is null
(not tested)
[линк]
Благодаря
не бях съобразил, че проверката се прави върху данните от декартовото произведение (т.е. резултата от left join-а), а не в самата таблица. Поради което можеш да правиш ... where b.pk is null
Re: Благодаря
Мне е декартовото произведение. Просто по дефиниция OUTER JOIN е INNER JOIN който е UNION ALL с NOT IN така някак:
SELECT a.*, b*
FROM a
JOIN b
ON a.pk = b.a_fkey
UNION ALL
SELECT a.*, NULL, NULL, NULL, ...
FROM a
WHERE a.pk NOT IN (SELECT a_fkey FROM b)
Аз лично ползвам old-school аналозите щото са >= бързи от OUTER JOIN-а (това при MSSQL). Чат-пат db-engine-а не може да съобрази, че няма да дублира редове от a заради JOIN-а. Със sub-select винаги се ориентира че резултатът е подмножество на a (логично като няма нищо друго във FROM клаузата:-)).
cheers,
</wqw>
[линк]
SELECT a.*, b*
FROM a
JOIN b
ON a.pk = b.a_fkey
UNION ALL
SELECT a.*, NULL, NULL, NULL, ...
FROM a
WHERE a.pk NOT IN (SELECT a_fkey FROM b)
Аз лично ползвам old-school аналозите щото са >= бързи от OUTER JOIN-а (това при MSSQL). Чат-пат db-engine-а не може да съобрази, че няма да дублира редове от a заради JOIN-а. Със sub-select винаги се ориентира че резултатът е подмножество на a (логично като няма нищо друго във FROM клаузата:-)).
cheers,
</wqw>
[линк]
composite keys
Всъщност и за множество ключове може така:
Но за големи стойности на b, по-добре е другото... в повечето случаи, и пак... прословутото зависи.
Everything louder than everything else...
SELECT
a.*
FROM
a
WHERE
(a.pk1, a.pk2) NOT IN (SELECT a_fkey1, a_fkey2 FROM b);
Но за големи стойности на b, по-добре е другото... в повечето случаи, и пак... прословутото зависи.
Everything louder than everything else...
Редактирано от Dakota на
Re: composite keys
MSSQL и Access не разбират от използване на tuples по този начин. Съвсем забравих, че бази данни = MySQL в този форум :-))
cheers,
</wqw>
[линк]
cheers,
</wqw>
[линк]
Re: composite keys
Е, това го ползвам в PostgreSQL. За MySQL изобщо не знам дали работи.
А иначе балимааму как е по стандарт.
Everything louder than everything else...
А иначе балимааму как е по стандарт.
Everything louder than everything else...
Re: "обратното" на join
Въпросче: трите варианта по-бързи ли ще са от това например и защо
SELECT a.id, a.a1, a.a2
FROM [а] LEFT JOIN [c] ON a.ID = c.id_a
GROUP BY a.id, a.a1, a.a2
HAVING (((Count(c.id))=0));
Сори на автора, че се възползвам от темата ;)
SELECT a.id, a.a1, a.a2
FROM [а] LEFT JOIN [c] ON a.ID = c.id_a
GROUP BY a.id, a.a1, a.a2
HAVING (((Count(c.id))=0));
Сори на автора, че се възползвам от темата ;)
Редактирано от _danitu на
Re: "обратното" на join
Е, това е най-лошият вариант дотук. Изпускаш питомното (WHERE), за да гониш дивото (HAVING). 
Everything louder than everything else...
Everything louder than everything else...