sql - এসকিউএল সার্ভার: প্রথম সারিতে যোগ দিতে কিভাবে




sql-server tsql (8)

আমি একটি কংক্রিট, কিন্তু hypothetical, উদাহরণ ব্যবহার করব।

প্রতিটি আদেশ সাধারণত শুধুমাত্র একটি লাইন আইটেম আছে :

আদেশ:

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

আমি কি সত্যিই চাই এসকিউএল সার্ভারের একটি বেছে নিতে হবে, কারণ এটি যথেষ্ট ভাল হবে :

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

কিন্তু যে ত্রুটি দেয়:

কলাম বা উপসর্গ 'আদেশ' না
একটি টেবিল নাম বা উপনাম নাম সঙ্গে মেলে
প্রশ্নের মধ্যে ব্যবহৃত।

সম্ভবত কারণ ভিতরের নির্বাচন বাইরের টেবিল দেখতে না।


, সাধারণ টেবিল অভিব্যক্তি ব্যবহার করে আরেকটি aproach:

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

@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

কখনও কখনও আপনি শুধুমাত্র পরীক্ষা যা ভাল কর্মক্ষমতা দেয় পরীক্ষা করতে হবে


আমি LEFT JOIN এবং Orders.OrderNumber দ্বারা GROUP ব্যবহার করে একই সমস্যা সমাধান করি। এই ভাবে এটি করার একটি কারণ নেই?

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 একসঙ্গে দুই যোগদান করে দেয়:

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

2 row(s) affected

যেখানে আমরা এটি শুধুমাত্র একটি সারি ফিরে চেয়েছিলেন:

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

1 row(s) affected

এই কারণে আমি GROUP BY Orders.OrderNumber ব্যবহার করি যা শুধুমাত্র OrderNumber প্রতি এক সারি প্রদান করে।


আমি জানি এই প্রশ্নের উত্তরটি কিছু আগে আগে দেওয়া হয়েছিল, কিন্তু বড় ডাটা সেটের সাথে ডিল করার সময় নেস্টেড প্রশ্নগুলি ব্যয়বহুল হতে পারে। এখানে একটি ভিন্ন সমাধান রয়েছে যেখানে নিছক ক্যোয়ারীটি শুধুমাত্র একবারই চলবে, পরিবর্তে প্রতিটি সারির জন্য।

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

এসকিউএল সার্ভার 2012 থেকে এবং পরবর্তীতে আমি মনে করি এটি কৌশলটি করবে:

SELECT DISTINCT
    o.OrderNumber ,
    FIRST_VALUE(li.Quantity) OVER ( PARTITION BY o.OrderNumber ORDER BY li.Description ) AS Quantity ,
    FIRST_VALUE(li.Description) OVER ( PARTITION BY o.OrderNumber ORDER BY li.Description ) AS Description
FROM    Orders AS o
    INNER JOIN LineItems AS li ON o.OrderID = li.OrderID

ক্রস চেষ্টা, চমত্কারভাবে কাজ করে, কিন্তু সামান্য আর লাগে। সামঞ্জস্যযুক্ত লাইন কলামগুলিতে সর্বোচ্চ এবং যোগ করা গোষ্ঠী রয়েছে যা গতি রাখে এবং অতিরিক্ত রেকর্ডকে বাদ দেয়।

এখানে সমন্বয়কৃত প্রশ্ন রয়েছে:

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

সম্পাদনা করুন: কখনোই না, Quassnoi একটি ভাল উত্তর আছে।

এসকিউএল ২ কে এর জন্য কিছু ভালো:

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

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 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

অনুগ্রহ করে লক্ষ্য করুন যে ORDER BY ছাড়া TOP 1 নির্ধারিত নয়: এই প্রশ্নের সাথে আপনি প্রতি অর্ডারের একটি লাইন আইটেম পাবেন, তবে এটি কোনটি এটি হবে তা সংজ্ঞায়িত করা হয় না।

প্রশ্নটির একাধিক অনুরোধ আপনাকে একই ক্রমের জন্য বিভিন্ন লাইন আইটেম দিতে পারে, এমনকি যদি অন্তর্নিহিত পরিবর্তন নাও ঘটে।

আপনি যদি নির্ধারক আদেশ চান তবে আপনাকে অন্তর্মুখী প্রশ্নের সাথে একটি ORDER BY যোগ করা উচিত।








sql-server-2000