送信された値のセットを少なくとも含む結果セットをクエリして取得する方法
Aug 21 2020
WITH fData AS
(
SELECT 1001 AS lookupID, 'A' AS LookUpValue UNION ALL
SELECT 1001 AS lookupID, 'B' AS LookUpValue UNION ALL
SELECT 1001 AS lookupID, 'C' AS LookUpValue UNION ALL
SELECT 1001 AS lookupID, 'D' AS LookUpValue UNION ALL
SELECT 1002 AS lookupID, 'A' AS LookUpValue UNION ALL
SELECT 1002 AS lookupID, 'Z' AS LookUpValue UNION ALL
SELECT 1002 AS lookupID, 'S' AS LookUpValue UNION ALL
SELECT 1002 AS lookupID, 'J' AS LookUpValue UNION ALL
SELECT 1003 AS lookupID, 'H' AS LookUpValue UNION ALL
SELECT 1003 AS lookupID, 'I' AS LookUpValue UNION ALL
SELECT 1003 AS lookupID, 'Z' AS LookUpValue UNION ALL
SELECT 1003 AS lookupID, 'C' AS LookUpValue
)
SELECT *
FROM fData fd
WHERE fd.LookUpValue IN ('A','B','C','D') /* This pulls back ANY record having these values and then return all of the records in that list. I want ONLY lists that have a minimum of these values. For example of my list only contained 'A' I would see both List 1001 records and List 1002 Records. */
;
私が提供したコードには、3つの偽のリストが含まれています。各リストには、値のセットが含まれています。指定した値を含むリスト内のすべてのレコードを取得するクエリを作成するにはどうすればよいですか。INステートメントを使用すると、それらのリスト値を含むすべてのリスト(レコード)が得られるため、機能しません。代わりに、指定した値の少なくともすべてを含むリストレコードのみを返す必要があります。
私の例では、4つの値(「A」、「B」、「C」、「D」)を指定したので、検索ID 1001の最初のリストのレコードのみが結果セットに表示されます。たとえば、単一の値を送信した場合'A'の値リスト1001とリスト1002の両方のリストには、少なくとも値 'A'が含まれているため、これらのすべてのレコードが表示されます。リスト1003には「A」の値がありません。
回答
3 forpas Aug 21 2020 at 18:02
lookupID
このクエリで必要なを取得します。
SELECT lookupID
FROM fData
WHERE LookUpValue IN ('A','B','C','D')
GROUP BY lookupID
HAVING COUNT(DISTINCT LookUpValue) = 4 -- the number of searched lookupvalues
演算子を使用したテーブルのすべての行IN
:
SELECT * FROM fData
WHERE lookupID IN (
SELECT lookupID
FROM fData
WHERE LookUpValue IN ('A','B','C','D')
GROUP BY lookupID
HAVING COUNT(DISTINCT LookUpValue) = 4
)
コードは標準SQLであり、(私が知っている)どのデータベースでも機能します。デモを
ご覧ください。結果:
> lookupID | LookUpValue
> -------: | :----------
> 1001 | A
> 1001 | B
> 1001 | C
> 1001 | D
dnoeth Aug 21 2020 at 21:51
forpasの変動は使用してクエリウィンドウ表示集合体の代わりに、グループ化を
WITH fData AS
(
SELECT 1001 AS lookupID, 'A' AS LookUpValue UNION ALL
SELECT 1001 AS lookupID, 'B' AS LookUpValue UNION ALL
SELECT 1001 AS lookupID, 'C' AS LookUpValue UNION ALL
SELECT 1001 AS lookupID, 'D' AS LookUpValue UNION ALL
SELECT 1001 AS lookupID, 'E' AS LookUpValue UNION ALL
SELECT 1002 AS lookupID, 'A' AS LookUpValue UNION ALL
SELECT 1002 AS lookupID, 'Z' AS LookUpValue UNION ALL
SELECT 1002 AS lookupID, 'S' AS LookUpValue UNION ALL
SELECT 1002 AS lookupID, 'J' AS LookUpValue UNION ALL
SELECT 1003 AS lookupID, 'H' AS LookUpValue UNION ALL
SELECT 1003 AS lookupID, 'I' AS LookUpValue UNION ALL
SELECT 1003 AS lookupID, 'Z' AS LookUpValue UNION ALL
SELECT 1003 AS lookupID, 'C' AS LookUpValue
),
cte as
(
SELECT *,
count(case when LookUpValue IN ('A','B','C','D') then 1 end)
over (partition by lookupID) as cnt
FROM fData
)
select lookupID, LookUpValue
from cte
where cnt = 4
これは、lookupID | LookUpValueの組み合わせが一意である場合にのみ機能します(これにより、DISTINCTが削除され、forpasクエリも簡略化されます)。
フィドルを見る