У меня есть следующая таблица в PostgreSQL:
id fid val
--------------------------
200 995 XXLL
200 996 XXLL
201 995 OOOP
201 996 OOOS
202 995 OKIL
202 996 OKIL
203 995 LLLL
203 996 CCCC
Я пытаюсь получить все id
с двумя строками для fid
995 и 996 и val
одинаковыми.
Итак, в приведенном выше примере я бы хотел, чтобы выходные данные SQL-запроса были просто 200, 202. Для 201 и 203 значения 995 и 996 разные.
Каков ожидаемый результат, если идентификатор также имеет идентификатор 999 с тем же или другим значением?
Таким образом, ожидаемый результат — это один столбец и две строки, показывающие значения 200 и 202. Верно? Или ты тоже хочешь показать вал? Или вы вообще хотите показать полные строки, то есть четыре строки для идентификаторов 200 и 202?
@jarlh Это мой вопрос в краткой версии;) А что делать, если для идентификатора 204 есть только строка 995, а для идентификатора 205 - только строка 996, а для идентификатора 206 нет ни того, ни другого? Вопрос действительно расплывчатый.
Я должен был упомянуть: все идентификаторы гарантированно имеют как 995, так и 996.
Чтобы получить лучший запрос, вы должны указать: точное определение таблицы (оператор CREATE TABLE
), мощность (сколько строк? сколько различных значений в fid
? всего 995 и 996?) и всегда вашу версию Postgres.
Что-то вроде этого:
SELECT qr2.id FROM
(SELECT id, val, count(1)
FROM table_1
GROUP BY id, val
HAVING count(1) > 1) qr1
JOIN
(SELECT id, fid
FROM table_1) qr2
ON qr1.id = qr2.id
GROUP BY qr2.id
ORDER BY qr2.id;
На основе ваших выборочных данных
SELECT X.ID,X.fid,X.val
FROM your_table AS X
JOIN
(
SELECT C.ID
FROM your_table AS C
GROUP BY C.id
HAVING MIN(C.VAL)=MAX(C.VAL)
)SQ ON X.id=SQ.id
Вы можете использовать INTERSECT
, чтобы найти строки, имеющие одинаковое значение для идентификатора.
select id from
(
select id, val from tablename where fid = 995
intersect
select id, val from tablename where fid = 996
) dt
Или просто сделайте GROUP BY
:
select id
from tablename
where fid in (995, 996)
group by id
having count(distinct val) = 1
and count(distinct fid) = 2; -- add to verify both 995 and 996 are there
Лучший ответ зависит от нераскрытых подробностей.
Если мы можем предположить ограничение PRIMARY KEY
для (id, fid)
или хотя бы индекс/ограничение UNIQUE
и оба столбца NOT NULL
или созданные с помощью NULLS NOT DISTINCT
- см.:
SELECT id
FROM tbl
WHERE fid IN (995, 996) -- only if there can be other fid
GROUP BY id, val -- !!
HAVING count(*) = 2
ORDER BY id; -- optional
Ключевой ингредиент — GROUP BY id, val
.
Работает даже для val IS NULL
(нулевые значения рассматриваются как равные).
В Postgres count(*)
быстрее, чем count(1)
или count(fid)
, и намного быстрее, чем count(DISTINCT fid)
.
Кроме того: если для 995 и 996 всегда есть строка, рассмотрите отдельные столбцы val_995
и val_996
. Проще, меньше стол, быстрее.
Почему второй столбец имеет значение? Разве не было бы достаточно просто проверить, появляется ли несколько значений для каждого идентификатора? По вашим выборочным данным этого будет достаточно. Если вам действительно необходимо задействовать второй столбец в вашей логике, улучшите пример данных, чтобы показать, почему и как это требуется.