web-dev-qa-db-ja.com

グループに対して条件が満たされた行を選択(一時テーブルなし)

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

しかし、私は思いついたグループ化を使用したソリューションを好みます。どんな助けでもありがたいです。

10
Piotr Falkowski

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 APPLYflag = 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
16

FlagBIT列または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)のみを持つ人を選択します。

TINYINTMAX引数を受け入れないため、BITへの変換が必要です。

4