그룹에 대해 조건이 충족 된 행을 선택합니다 (임시 테이블 없음).


10

열이 3 개인 테이블이있는 경우 :

ID  category    flag
1       A       1
2       A       0
3       A       0
4       B       0
5       C       0

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

그러나 그룹화 솔루션을 선호합니다. 도움을 주시면 감사하겠습니다.

답변:


16

GROUP BY그룹당 하나의 행만 반환하므로 단독으로 사용할 수 없습니다 ( category).


  • 당신과 함께 하위 쿼리 사용할 수 있습니다 flag = 1INNER 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각 카테고리에 대해 하나의 행만 가질 수있는 경우 필요하지 않습니다 flag = 1.

산출:

ID  category    flag
1       A       1
2       A       0
3       A       0

IN 술어에는 DISTINCT가 필요하지 않습니다. 그리고 카테고리 당 하나의 행만 플래그 1을 가질 수 있으면 DISTINCT는 전혀 필요하지 않습니다.
Andriy M

IN쿼리 에 대해 @AndriyM이 정확 합니다. 그러나 OP에는 " 카테고리 당 플래그가 1 이상인 모든 행을 선택하고 싶습니다. "라는 메시지가 DISTINCT있으므로 다른 쿼리에 필요 하다고 생각 합니다.
ypercubeᵀᴹ

1
그리고에서 CROSS APPLY의은 SELECT DISTINCT category으로 대체하면 아마 더 효율적이어야한다 SELECT TOP (1) whatever. 효과적으로 EXISTS하위 쿼리 를 작성하는 다른 방법 입니다.
ypercubeᵀᴹ

@Andriy 그렇기 때문에 어제 귀하의 초기 의견을 바탕으로 메모를 추가했습니다. flag = 1 인 행이 1 개만있는 경우 필요하지 않습니다.
Julien Vavasseur

4

그 가정하면 FlagA는 BIT열 또는 INT만 소요 01값으로,이 아니라 윈도 윙 함수를 사용하여 달성 될 수있다. 예를 들어 :

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(1).

인수를 허용하지 않으므로로 변환해야 TINYINT합니다 .MAXBIT

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.