"обратното" на join

9 отговора 0 прегледа
#1

"обратното" на join

Здравейте.

Представете си две таблици, свързани в съотношение 1:n - в едната има id и някакви данни, а в другата ключ към първата и нейните си данни; във втората няколко реда могат да имат един и същ външен ключ.

Питането е следното: как да вземем тези редове от първата таблица, към които няма ключ във втората?

Сещам се за един начин, но ми се струва неразумен от гледна точка на производителност:
select distinct a.* from a, b where a.id != b.a_fkey 


Предполагам, че решението е очевидно, но не се сещам. Идеи?

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

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)


[линк]
Отговор
в отговор на wqw #3

Благодаря



не бях съобразил, че проверката се прави върху данните от декартовото произведение (т.е. резултата от left join-а), а не в самата таблица. Поради което можеш да правиш ... where b.pk is null

Отговор
в отговор на Masklin #4

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>


[линк]
Отговор
в отговор на wqw #5

composite keys

Всъщност и за множество ключове може така:

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 на

Отговор
в отговор на Dakota #6

Re: composite keys

MSSQL и Access не разбират от използване на tuples по този начин. Съвсем забравих, че бази данни = MySQL в този форум :-))

cheers,
</wqw>


[линк]
Отговор
в отговор на wqw #7

Re: composite keys

амии по скоро ти приемаш за база данни за MSSQL или access

Отговор
в отговор на wqw #8

Re: composite keys

Е, това го ползвам в PostgreSQL. За MySQL изобщо не знам дали работи.

А иначе балимааму как е по стандарт.

Everything louder than everything else...
Отговор
в отговор на wqw #9

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));

Сори на автора, че се възползвам от темата ;)

Редактирано от _danitu на

Отговор
в отговор на _danitu #10

Re: "обратното" на join

Е, това е най-лошият вариант дотук. Изпускаш питомното (WHERE), за да гониш дивото (HAVING).

Everything louder than everything else...
Отговор