Найти строки по крайней мере с n строками в другой таблице без объединений - PullRequest
0 голосов
/ 04 июня 2019

У меня есть таблица как таковая (tbl):

+----+------+-----+
| pk | attr | val |
+----+------+-----+
|  0 | ohif |   4 |
|  1 | foha |  56 |
|  2 | slns |   2 |
|  3 | faso |  11 |
+----+------+-----+

И еще одна таблица в соотношении n-к-1 с tbl (tbl2):

+----+-----+
| pk | rel |
+----+-----+
|  0 |   0 |
|  1 |   1 |
|  2 |   0 |
|  3 |   2 |
|  4 |   2 |
|  5 |   3 |
|  6 |   1 |
|  7 |   2 |
+----+-----+

(tbl2.rel -> tbl.pk.)

Я хотел бы выбрать только строки из tbl, которые связаны как минимум с n строками из tbl2.

Т.е. для n = 2 мне нужна эта таблица:

+----+------+-----+
| pk | attr | val |
+----+------+-----+
|  0 | ohif |   4 |
|  1 | foha |  56 |
|  2 | slns |   2 |
+----+------+-----+

Вот решение, которое я придумал:

SELECT DISTINCT ON (tbl.pk) tbl.*
FROM (
    SELECT tbl.pk
    FROM tbl
    RIGHT OUTER JOIN tbl2 ON tbl2.rel = tbl.pk
    GROUP BY tbl.pk
    HAVING COUNT(tbl2.*) >= 2  -- n
) AS tbl_candidates
LEFT OUTER JOIN tbl ON tbl_candidates.pk = tbl.pk

Можно ли это сделать безВыбор кандидатов с подзапросом и повторное объединение таблицы с самим собой?

Я на Postgres 10. Стандартное решение SQL было бы лучше, но решение Postgres приемлемо.

1 Ответ

0 голосов
/ 04 июня 2019

ОК, просто присоединитесь один раз, как показано ниже:

select
    t1.pk,
    t1.attr,
    t1.val
from
    tbl t1
join
    tbl2 t2 on t1.pk = t2.rel
group by
    t1.pk,
    t1.attr,
    t1.val
having(count(1)>=2) order by t1.pk;
 pk | attr | val 
----+------+-----
  0 | ohif |   4
  1 | foha |  56
  2 | slns |   2
(3 rows)

Или просто присоединитесь один раз и используйте CTE(with clause), как показано ниже:

with tmp as (
select rel from tbl2 group by rel having(count(1)>=2)
)
select b.* from tmp t join tbl b on t.rel = b.pk order by b.pk;
 pk | attr | val 
----+------+-----
  0 | ohif |   4
  1 | foha |  56
  2 | slns |   2
(3 rows)

Является ли SQL более понятным?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...