|
Тема
|
"обратното" на join
|
|
Автор |
Masklin (ном) |
Публикувано | 04.03.08 18:53 |
|
Здравейте.
Представете си две таблици, свързани в съотношение 1:n - в едната има id и някакви данни, а в другата ключ към първата и нейните си данни; във втората няколко реда могат да имат един и същ външен ключ.
Питането е следното: как да вземем тези редове от първата таблица, към които няма ключ във втората?
Сещам се за един начин, но ми се струва неразумен от гледна точка на производителност: select distinct a.* from a, b where a.id != b.a_fkey
Предполагам, че решението е очевидно, но не се сещам. Идеи?
| |
Тема
|
Re: "обратното" на join
[re: Masklin]
|
|
Автор |
wqw (АзСъмЖив) |
Публикувано | 04.03.08 19:33 |
|
-- 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)
| |
Тема
|
Благодаря
[re: wqw]
|
|
Автор |
Masklin (ном) |
Публикувано | 05.03.08 13:56 |
|
не бях съобразил, че проверката се прави върху данните от декартовото произведение (т.е. резултата от left join-а), а не в самата таблица. Поради което можеш да правиш ... where b.pk is null
| |
Тема
|
Re: Благодаря
[re: Masklin]
|
|
Автор |
wqw (АзСъмЖив) |
Публикувано | 05.03.08 19:59 |
|
Мне е декартовото произведение. Просто по дефиниция 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>
| |
Тема
|
composite keys
[re: wqw]
|
|
Автор |
Dakota (erotoman) |
Публикувано | 07.03.08 15:26 |
|
Всъщност и за множество ключове може така:
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 на 07.03.08 15:28.
| |
Тема
|
Re: composite keys
[re: Dakota]
|
|
Автор |
wqw (АзСъмЖив) |
Публикувано | 11.03.08 17:21 |
|
MSSQL и Access не разбират от използване на tuples по този начин. Съвсем забравих, че бази данни = MySQL в този форум :-))
cheers,
</wqw>
| |
Тема
|
Re: composite keys
[re: wqw]
|
|
Автор |
phpGuru (непознат
) |
Публикувано | 12.03.08 15:13 |
|
амии по скоро ти приемаш за база данни за MSSQL или access
| |
Тема
|
Re: composite keys
[re: wqw]
|
|
Автор |
Dakota (erotoman) |
Публикувано | 12.03.08 21:13 |
|
Е, това го ползвам в PostgreSQL. За MySQL изобщо не знам дали работи.
А иначе балимааму как е по стандарт.
Everything louder than everything else...
| |
Тема
|
Re: "обратното" на join
[re: wqw]
|
|
Автор |
_danitu (аз) |
Публикувано | 19.03.08 14:52 |
|
Въпросче: трите варианта по-бързи ли ще са от това например и защо
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 на 19.03.08 14:54.
| |
Тема
|
Re: "обратното" на join
[re: _danitu]
|
|
Автор |
Dakota (erotoman) |
Публикувано | 19.03.08 20:46 |
|
Е, това е най-лошият вариант дотук. Изпускаш питомното (WHERE), за да гониш дивото (HAVING).
Everything louder than everything else...
| |
|
|
|
|