sql एसक्यूएल सर्वर: पहली पंक्ति में कैसे शामिल हों




sql-server tsql (8)

संपादित करें: कभी नहीं, Quassnoi का एक बेहतर जवाब है।

SQL2K के लिए, ऐसा कुछ:

SELECT 
  Orders.OrderNumber
, LineItems.Quantity
, LineItems.Description
FROM (  
  SELECT 
    Orders.OrderID
  , Orders.OrderNumber
  , FirstLineItemID = (
      SELECT TOP 1 LineItemID
      FROM LineItems
      WHERE LineItems.OrderID = Orders.OrderID
      ORDER BY LineItemID -- or whatever else
      )
  FROM Orders
  ) Orders
JOIN LineItems 
  ON LineItems.OrderID = Orders.OrderID 
 AND LineItems.LineItemID = Orders.FirstLineItemID

मैं एक ठोस, लेकिन काल्पनिक, उदाहरण का उपयोग करेंगे।

प्रत्येक आदेश में आमतौर पर केवल एक पंक्ति वस्तु होती है :

आदेश:

OrderGUID   OrderNumber
=========   ============
{FFB2...}   STL-7442-1      
{3EC6...}   MPT-9931-8A

लाइन आइटम:

LineItemGUID   Order ID Quantity   Description
============   ======== ========   =================================
{098FBE3...}   1        7          prefabulated amulite
{1609B09...}   2        32         spurving bearing

लेकिन कभी-कभी दो पंक्ति वस्तुओं के साथ एक आदेश होगा:

LineItemID   Order ID    Quantity   Description
==========   ========    ========   =================================
{A58A1...}   6,784,329   5          pentametric fan
{0E9BC...}   6,784,329   5          differential girdlespring 

आम तौर पर उपयोगकर्ता को आदेश दिखाते समय:

SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
    INNER JOIN LineItems 
    ON Orders.OrderID = LineItems.OrderID

मैं आदेश पर एक ही आइटम दिखाना चाहता हूं। लेकिन इस प्रासंगिक आदेश के साथ दो (या अधिक) आइटम होते हैं, ऑर्डर डुप्लीकेट दिखाई देंगे :

OrderNumber   Quantity   Description
===========   ========   ====================
STL-7442-1    7          prefabulated amulite
MPT-9931-8A   32         spurving bearing
KSG-0619-81   5          panametric fan
KSG-0619-81   5          differential girdlespring

मैं वास्तव में चाहता हूं कि SQL सर्वर सिर्फ एक चुनें , क्योंकि यह पर्याप्त होगा :

OrderNumber   Quantity   Description
===========   ========   ====================
STL-7442-1    7          prefabulated amulite
MPT-9931-8A   32         differential girdlespring
KSG-0619-81   5          panametric fan

अगर मैं साहसी हो जाता हूं, तो मैं उपयोगकर्ता को यह दिखाने के लिए एक इलिप्सिस दिखा सकता हूं कि एक से अधिक हैं:

OrderNumber   Quantity   Description
===========   ========   ====================
STL-7442-1    7          prefabulated amulite
MPT-9931-8A   32         differential girdlespring
KSG-0619-81   5          panametric fan, ...

तो सवाल यह है कि कैसे या तो

  • "डुप्लिकेट" पंक्तियों को खत्म करें
  • नकल से बचने के लिए केवल पंक्तियों में से एक में शामिल हों

पहला प्रयास

मेरा पहला निष्पक्ष प्रयास केवल " टॉप 1 " लाइन आइटम में शामिल होना था:

SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
    INNER JOIN (
       SELECT TOP 1 LineItems.Quantity, LineItems.Description
       FROM LineItems
       WHERE LineItems.OrderID = Orders.OrderID) LineItems2
    ON 1=1

लेकिन यह त्रुटि देता है:

कॉलम या उपसर्ग 'ऑर्डर' क्वेरी में उपयोग किए गए तालिका नाम या उपनाम नाम से मेल नहीं खाता है।

संभवतः क्योंकि आंतरिक चयन बाहरी तालिका नहीं देखता है।


मुझे पता है कि इस प्रश्न का उत्तर थोड़ी देर पहले दिया गया था, लेकिन बड़े डेटा सेट से निपटने पर, घोंसला वाले प्रश्न महंगा हो सकते हैं। यहां एक अलग समाधान है जहां नेस्टेड क्वेरी केवल एक बार दौड़ दी जाएगी, प्रत्येक पंक्ति के बदले में।

SELECT 
  Orders.OrderNumber,
  LineItems.Quantity, 
  LineItems.Description
FROM 
  Orders
  INNER JOIN (
    SELECT
      Orders.OrderNumber,
      Max(LineItem.LineItemID) AS LineItemID
    FROM
      Orders INNER JOIN LineItems
      ON Orders.OrderNumber = LineItems.OrderNumber
    GROUP BY Orders.OrderNumber
  ) AS Items ON Orders.OrderNumber = Items.OrderNumber
  INNER JOIN LineItems 
  ON Items.LineItemID = LineItems.LineItemID

SELECT   Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM     Orders
JOIN     LineItems
ON       LineItems.LineItemGUID =
         (
         SELECT  TOP 1 LineItemGUID 
         FROM    LineItems
         WHERE   OrderID = Orders.OrderID
         )

SQL Server 2005 और ऊपर में, आप केवल CROSS APPLY साथ INNER JOIN को प्रतिस्थापित कर सकते हैं:

SELECT  Orders.OrderNumber, LineItems2.Quantity, LineItems2.Description
FROM    Orders
CROSS APPLY
        (
        SELECT  TOP 1 LineItems.Quantity, LineItems.Description
        FROM    LineItems
        WHERE   LineItems.OrderID = Orders.OrderID
        ) LineItems2

सहसंबंधित उप प्रश्न उप प्रश्न हैं जो बाहरी क्वेरी पर निर्भर करते हैं। यह एसक्यूएल में लूप के लिए है। बाहरी क्वेरी में प्रत्येक पंक्ति के लिए उप-क्वेरी एक बार चलती है:

select * from users join widgets on widgets.id = (
    select id from widgets
    where widgets.user_id = users.id
    order by created_at desc
    limit 1
)

मैं बाएं जॉइन और ऑर्डर द्वारा ऑर्डर करने के द्वारा एक समान समस्या हल करता हूं। ऑर्डर नम्बर। क्या ऐसा कोई कारण नहीं है?

SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
    LEFT JOIN LineItems 
    ON Orders.OrderID = LineItems.OrderID
GROUP BY Orders.OrderNumber

मैं आपके उत्तर प्रश्न का उत्तर अपने प्रश्न में उत्तर के साथ दूंगा:

Orders             LineItems
+-------------+    +---------+----------+---------------+
| OrderNumber |    | OrderID | Quantity | Description   |
+-------------+    +---------+----------+---------------+
| 22586       |    | 22586   | 17       | Trunion       |
+-------------+    | 22586   | 3        | Girdle Spring |
                   +---------+----------+---------------+

ऑर्डर नम्बर पर दोनों में शामिल होने से:

OrderNumber  Quantity  Description
-----------  --------  -------------
22586        17        Trunion
22586        3         Girdle Spring

2 row(s) affected

जहां हम चाहते थे कि यह केवल एक पंक्ति वापस करे:

OrderNumber  Quantity  Description
-----------  --------  -------------
22586        17        Trunion

1 row(s) affected

यही कारण है कि मैं ग्रुप बाय ऑर्डर का उपयोग करता हूं। ऑर्डर नम्बर जो केवल ऑर्डर नम्बर पर एक पंक्ति देता है।


@Quassnoi उत्तर अच्छा है, कुछ मामलों में (विशेष रूप से यदि बाहरी तालिका बड़ी है), खिड़की वाले कार्यों का उपयोग करने के साथ एक और अधिक कुशल क्वेरी हो सकती है, जैसे:

SELECT  Orders.OrderNumber, LineItems2.Quantity, LineItems2.Description
FROM    Orders
LEFT JOIN 
        (
        SELECT  LineItems.Quantity, LineItems.Description, OrderId, ROW_NUMBER()
                OVER (PARTITION BY OrderId ORDER BY (SELECT NULL)) AS RowNum
        FROM    LineItems

        ) LineItems2 ON LineItems2.OrderId = Orders.OrderID And RowNum = 1

कभी-कभी आपको यह जांचने की आवश्यकता होती है कि कौन सी क्वेरी बेहतर प्रदर्शन देती है।


, आम टेबल अभिव्यक्ति का उपयोग कर एक और अपमान:

with firstOnly as (
    select Orders.OrderNumber, LineItems.Quantity, LineItems.Description, ROW_NUMBER() over (partiton by Orders.OrderID order by Orders.OrderID) lp
    FROM Orders
        join LineItems on Orders.OrderID = LineItems.OrderID
) select *
  from firstOnly
  where lp = 1

या, अंत में आप सभी पंक्तियों को शामिल करना चाहते हैं?

कॉमा अलग संस्करण यहाँ:

  select *
  from Orders o
    cross apply (
        select CAST((select l.Description + ','
        from LineItems l
        where l.OrderID = s.OrderID
        for xml path('')) as nvarchar(max)) l
    ) lines

क्रॉस का प्रयास किया, अच्छी तरह से काम करता है, लेकिन थोड़ा अधिक समय लगता है। समायोजित लाइन कॉलम अधिकतम और जोड़ा समूह है जो गति रखता है और अतिरिक्त रिकॉर्ड गिरा देता है।

समायोजित क्वेरी यहां दी गई है:

SELECT Orders.OrderNumber, max(LineItems.Quantity), max(LineItems.Description)
FROM Orders
    INNER JOIN LineItems 
    ON Orders.OrderID = LineItems.OrderID
Group by Orders.OrderNumber






sql-server-2000