grup için koşulu karşılanan satırları seç (geçici tablo olmadan)


10

3 sütunlu tablo:

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

flag = 1Kategori başına en az bir kez olan tüm satırları seçmek istiyorum .

Beklenen sonuçlar:

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

Aşağıdaki gibi geçici bir tablo kullanılarak çözülebilir:

select ID into #tempTable from someTable where flag = 1
select * from someTable join #tempTable on someTable.ID = #tempTable.ID

Ama gruplandırmayla çözmeyi tercih ettiğim bir çözüm tercih ederdim. Herhangi bir yardım takdir edilecektir.

Yanıtlar:


16

GROUP BYGrup başına yalnızca 1 satır döndürdüğü için tek başına kullanılamaz ( category).


  • Sen bir alt sorgusu kullanabilirsiniz flag = 1ve 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 ;
  • Yan EXISTStümcesi kullanabilirsiniz :

    SELECT d.ID, d.category, d.flag
    FROM data d
    WHERE EXISTS (
        SELECT 1 FROM data WHERE flag = 1 AND category = d.category
    ) ;   
  • INMaddeyi kullanabilirsiniz ( EXISTSdaha iyi olmasına rağmen ):

    SELECT d.ID, d.category, d.flag
    FROM data d
    WHERE d.category IN (SELECT category FROM data WHERE flag = 1) ;
  • Aşağıdakiler CROSS APPLYüzerinde bir alt sorgu ile de kullanabilirsiniz 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 ;

DISTINCTher kategori için sadece 1 satır varsa gerekli değildir flag = 1.

Çıktı:

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

DISTINCT, IN yüklemi için gereksizdir. Ve her kategori için yalnızca bir satır 1 bayrağına sahipse, DISTINCT hiç gereksiz değildir.
Andriy M

@AndriyM INsorgu hakkında doğru . Ama OP " diğer sorgularda gerekli olduğunu düşündürüyor bana" her kategoride bayrak = 1 olan tüm satırları seçmek istiyorum "vardır DISTINCT.
ypercubeᵀᴹ

1
Ve de CROSS APPLY, SELECT DISTINCT categorydeğiştirilir eğer muhtemelen daha verimli olmalıdır SELECT TOP (1) whatever. Bir EXISTSalt sorgu yazmanın başka bir yolu etkili olacaktır .
ypercubeᵀᴹ

@Andriy Bu yüzden dün ilk yorumunuza dayanarak bir not ekledim: bayrak = 1 ile sadece 1 satır varsa gerekli değildir
Julien Vavasseur

4

Bunun yalnızca ve değer olarak Flagalan bir BITsütun ya da bir sütun olduğu varsayılarak, pencereli işlevler kullanılarak da gerçekleştirilebilir. Örneğin:INT01

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;

Bu çıktı:

ID Category Flag  
-- -------- ----- 
1  A        True  
2  A        False 
3  A        False 

Bu, Flagtablonuzdaki her kategori için en yüksek olanı bulacaktır, sizin durumunuzda büyük olasılıkla yalnızca doğru / yanlış ve yalnızca birine sahip olanı seçin true(1).

Bir argümanı kabul etmediği için dönüşüme TINYINTihtiyaç var .MAXBIT

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.