3列のテーブルがある場合:
ID category flag
1 A 1
2 A 0
3 A 0
4 B 0
5 C 0
カテゴリごとに少なくとも1回、flag = 1
を含むすべての行を選択したい。
予期された結果:
ID category flag
1 A 1
2 A 0
3 A 0
次のような一時テーブルを使用して解決できます。
select ID into #tempTable from someTable where flag = 1
select * from someTable join #tempTable on someTable.ID = #tempTable.ID
しかし、私は思いついたグループ化を使用したソリューションを好みます。どんな助けでもありがたいです。
GROUP BY
は、グループごとに1行(category
)しか返さないため、単独では使用できません。
flag = 1
およびINNER JOIN
でサブクエリを使用できます。
SELECT d1.ID, d1.category, d1.flag
FROM data d1
INNER JOIN (
SELECT DISTINCT category FROM data WHERE flag = 1
) d2
ON d2.category = d1.category ;
EXISTS
句を使用できます。
SELECT d.ID, d.category, d.flag
FROM data d
WHERE EXISTS (
SELECT 1 FROM data WHERE flag = 1 AND category = d.category
) ;
IN
句を使用できます(ただし、EXISTS
の方が適しています)。
SELECT d.ID, d.category, d.flag
FROM data d
WHERE d.category IN (SELECT category FROM data WHERE flag = 1) ;
CROSS APPLY
をflag = 1
に対するサブクエリで使用することもできます。
SELECT d.ID, d.category, d.flag
FROM data d
CROSS APPLY (
SELECT TOP (1) category
FROM data
WHERE flag = 1 AND category = d.category
) ca ;
DISTINCT
は、カテゴリごとに1行のみがflag = 1
を持つことができる場合は必要ありません。
ID category flag
1 A 1
2 A 0
3 A 0
Flag
がBIT
列またはINT
であり、_0
_および_1
_のみを値として取ると仮定すると、ウィンドウ関数を使用して次のように実現できます。上手。例えば:
_DECLARE @Test TABLE
(
ID INT
, Category VARCHAR(1)
, Flag BIT
);
INSERT INTO @Test (ID, Category, Flag)
VALUES (1, 'A', 1)
, (2, 'A', 0)
, (3, 'A', 0)
, (4, 'B', 0)
, (5, 'C', 0);
SELECT T.ID
, T.Category
, T.Flag
FROM (
SELECT ID
, Category
, Flag
, MAX(CAST(Flag AS TINYINT)) OVER(PARTITION BY Category) AS MaxFlag
FROM @Test
) AS T
WHERE T.MaxFlag = 1;
_
それが出力です:
_ID Category Flag
-- -------- -----
1 A True
2 A False
3 A False
_
これは、テーブル内の各カテゴリの最も高いFlag
を検索します。この場合、おそらくtrue/falseのみであり、true(1)
のみを持つ人を選択します。
TINYINT
はMAX
引数を受け入れないため、BIT
への変換が必要です。