SQL получить ВСЕ строки с общими внешними ключами - PullRequest
0 голосов
/ 13 января 2020

I sh, чтобы найти ВСЕ строки, которые имеют хотя бы одного брата с некоторым (не указанным c) внешним ключом.

mytable
id |fk_id    
---|--------
1  |100 
2  |200
3  |200
4  |300 
5  |300
6  |300

Мой запрос должен возвращать строки 2-6, но не строка 1, поскольку она одна.

Я придумала рабочее решение, которое использует 2 подзапроса, что кажется слишком много. (Выполнение нескольких секунд на 20 000 строк +, что подразумевает, по крайней мере, O (n ^ 2)

SELECT * from mytable 
WHERE fk_id IN 
  (SELECT fk_id FROM
    (SELECT fk_id, SUM(fk_id) as mycnt from mytable GROUP BY fk_id)
  WHERE mycnt >= 2)

Что будет более быстрым решением?

Обычное программирование Не SQL решение будет просто отсортировать по fk_id, а затем избавиться от синглов, которые были бы O (nlogn) для родовой c сортировки плюс O (n) просто итерировать один раз, поэтому O (nlogn)

с использованием SQLite, но другие SQL диалекты тоже хорошо.

Ответы [ 2 ]

4 голосов
/ 13 января 2020

С EXISTS:

SELECT m.* FROM mytable m
WHERE EXISTS (
  SELECT 1 FROM mytable
  WHERE id <> m.id AND fk_id = m.fk_id
)

См. Демоверсию . Или с оконной функцией COUNT ():

SELECT m.id, m.fk_id 
FROM (
  SELECT *, COUNT(id) OVER (PARTITION BY fk_id) counter  
  FROM mytable
) m
WHERE m.counter > 1

См. Демоверсию . Результаты:

| id  | fk_id |
| --- | ----- |
| 2   | 200   |
| 3   | 200   |
| 4   | 300   |
| 5   | 300   |
| 6   | 300   |
2 голосов
/ 13 января 2020

Примерно так должно работать:

select * 
from mytable
where fk_id in (
  select fk_id
  from mytable
  group by fk_id
  having count(*) > 1
)

Еще один вариант использования inner join:

select * 
from mytable m
inner join
(
  select fk_id
  from mytable
  group by fk_id
  having count(*) > 1
) fks on fks.fk_id = m.fk_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...