समूह (अस्थायी तालिका के बिना) के लिए मिलने वाली पंक्तियों का चयन करें


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अकेले उपयोग नहीं किया जा सकता क्योंकि यह केवल प्रति समूह 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

INIST के लिए DISTINCT अनावश्यक है। और अगर प्रति श्रेणी केवल एक पंक्ति में 1 का झंडा हो सकता है, तो DISTINCT बिल्कुल भी अनावश्यक है।
एंड्री एम

@AndriyM INक्वेरी के बारे में सही है । लेकिन ओपी के पास " मैं उन सभी पंक्तियों का चयन करना चाहता हूं जिनमें झंडा = 1 प्रति वर्ग में कम से कम एक बार " है जो मुझे लगता है कि DISTINCTअन्य प्रश्नों में आवश्यक है।
ypercube y

1
और में CROSS APPLY, SELECT DISTINCT categoryशायद अधिक कुशल होना चाहिए अगर के साथ बदल दिया SELECT TOP (1) whatever। यह प्रभावी रूप से एक EXISTSउपश्रेणी लिखने का एक और तरीका होगा ।
ypercube y

@Andriy यही कारण है कि मैं एक नोट कल अपने प्रारंभिक टिप्पणी के आधार पर कहा: की जरूरत नहीं है, अगर वहाँ झंडा = 1. साथ ही 1 पंक्ति
जुलिएन Vavasseur

4

मान लें कि 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(1)

रूपांतरण TINYINTकी आवश्यकता है क्योंकि MAXएक BITतर्क को स्वीकार नहीं करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.