প্রথম সারিতে কীভাবে যোগদান করবেন


773

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

প্রতিটি অর্ডারে সাধারণত একটি লাইন আইটেম থাকে :

আদেশ:

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

তবে এটি ত্রুটি দেয়:

কলামে বা উপসর্গ 'অর্ডারস' কোয়েরিতে ব্যবহৃত
টেবিলের নাম বা উপনামের সাথে মেলে না

সম্ভবত কারণ অভ্যন্তরীণ নির্বাচন বাইরের সারণিটি দেখতে পায় না।


3
আপনি ব্যবহার করতে পারবেন না group by?
দারুশ জাফারি

2
আমি মনে করি (এবং আমি ভুল হলে আমাকে সংশোধন করি) এর জন্য group byযেখানে আপনি সদৃশ চান না সেগুলি বাদ দিয়ে অন্যান্য সমস্ত কলামের তালিকা তৈরি করতে হবে। সূত্র
জোশুয়া নেলসন

উত্তর:


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

এসকিউএল সার্ভার 2005 এবং তারপরে, আপনি কেবল এর সাথে প্রতিস্থাপন INNER JOINকরতে পারেন CROSS APPLY:

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

দয়া করে মনে রাখবেন যে TOP 1ছাড়াই ORDER BYনিরোধক নয়: এই ক্যোয়ারী আপনি প্রতি আদেশ অনুযায়ী একটি লাইন আইটেম পাবেন, তবে এটি কোনটি হবে তা নির্ধারণ করা হয়নি।

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

আপনি যদি ডিটারমিনিস্টিক অর্ডার চান তবে ORDER BYআপনার আন্তঃতম কোয়েরিতে একটি ধারা যুক্ত করা উচিত ।


3
দুর্দান্ত, যে কাজ করে; ধারাটিতে যোগদানের জন্য টেবিলের ধারাটি থেকে প্রথম 1 সরানো।
আয়ান বয়ড

107
এবং "আউটর জয়েন" সমতুল্য হবে "আউটর অ্যাপ্লাই"
অ্যালেক্স

9
বাম আউটরের যোগদানের জন্য কীভাবে?
অ্যালেক্স নোলাস্কো

8
যদি যোগদানটি কোনও যৌগিক কী দ্বারা হয় / একাধিক কলাম থাকে তবে আপনি এটি কীভাবে করবেন?
ব্রেট রায়ান

7
CROSS APPLYপরিবর্তে INNER JOINএবং OUTER APPLYপরিবর্তে LEFT JOIN(একই হিসাবে LEFT OUTER JOIN)।
মিনিটে হস্টব্লব

117

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

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

2
আপনার 'লাইন আইটেম আইডি' কলামটি সঠিকভাবে সূচিযুক্ত না করা হলে এটি আরও দ্রুত । স্বীকৃত উত্তরের তুলনায়।
GER

3
আপনি যেভাবে ফিরে যেতে চান তার চেয়ে আলাদা কলামের মাধ্যমে অর্ডার করা দরকার হিসাবে আপনি যদি ম্যাক্স ব্যবহারযোগ্য না হন তবে আপনি কীভাবে এটি করবেন?
নিকজি

2
আপনি যে কোনও উপায়ে চাইলে উত্পন্ন টেবিলটি অর্ডার করতে পারেন এবং এসকিউএল সার্ভারে শীর্ষস্থানীয় 1 বা মাইএসকিউএলে
লিমিটেড

28

আপনি করতে পারেন:

SELECT 
  Orders.OrderNumber, 
  LineItems.Quantity, 
  LineItems.Description
FROM 
  Orders INNER JOIN LineItems 
  ON Orders.OrderID = LineItems.OrderID
WHERE
  LineItems.LineItemID = (
    SELECT MIN(LineItemID) 
    FROM   LineItems
    WHERE  OrderID = Orders.OrderID
  )

এটির জন্য একটি সূচক (বা প্রাথমিক কী) প্রয়োজন LineItems.LineItemIDএবং LineItems.OrderIDএটিতে একটি সূচক প্রয়োজন বা এটি ধীর হবে।


2
যদি কোনও অর্ডারগুলিতে লাইন আইটেম না থাকে তবে এটি কাজ করে না। সাব-এক্সপ্রেশনটি পরে LineItems.LineItemID = nullফলাফল থেকে সম্পূর্ণ বাম সত্তার আদেশগুলি মূল্যায়ন করে এবং অপসারণ করে।
লিও

6
এটি অভ্যন্তরীণ যোগদানের প্রভাবও তাই, হ্যাঁ।
টমলক

1
সলিউশন যা লেফট আউট জয়েনের জন্য অভিযোজিত হতে পারে: stackoverflow.com/a/20576200/510583
লিও

3
@ লেও হ্যাঁ, তবে ওপি নিজেই একটি অভ্যন্তরীণ যোগদান ব্যবহার করেছিল, তাই আমি আপনার আপত্তি বুঝতে পারি না।
টমলক

27

@ কাসনোই উত্তরটি ভাল, কিছু ক্ষেত্রে (বিশেষত যদি বাইরের টেবিলটি বড় হয়), উইন্ডোড ফাংশনগুলি ব্যবহার করার সাথে আরও দক্ষ ক্যোয়ারী হতে পারে:

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

কখনও কখনও আপনার কেবল পরীক্ষার দরকার হয় কোন কোয়েরি আরও ভাল পারফরম্যান্স দেয়।


3
এটিই কেবলমাত্র আমি উত্তর পেয়েছি যা সত্যই "বাম" যোগ দেয়, এর অর্থ এটি "বাম" টেবিলের পরে আর কোনও লাইন যুক্ত করে না। আপনাকে কেবল সাব-কোয়েরিতে রাখতে হবে এবং "যেখানে রোউনাম নাল নয়" যুক্ত করতে হবে
ব্যবহারকারী 890332

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

এটি একটি ভাল সমাধান। দয়া করে নোট করুন: আপনার নিজের পরিস্থিতির জন্য ব্যবহার করার সময় আপনি কীভাবে বিভাজন (সাধারণত আপনি সেখানে কিছু আইডি কলাম চান) এবং অর্ডার বাই (যা কোনও কিছুর দ্বারা সম্পন্ন হতে পারে, আপনি কোন সারিতে রাখতে চান তার উপর নির্ভর করে) কীভাবে সতর্ক হন? ডেটক্রিটেড ডেস্ক কয়েকটি টেবিলের জন্য এক পছন্দ হতে পারে তবে এটি অনেকগুলি বিষয়ের উপর নির্ভর করবে)
জোসেফডোগি

14

, সাধারণ টেবিল এক্সপ্রেশন ব্যবহার করে অন্য একটি 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

13

এসকিউএল সার্ভার থেকে 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

2
আপনি আমাকে জিজ্ঞাসা করলে সেরা উত্তর।
থমাস

11

সম্পর্কযুক্ত সাব-কোয়েরিগুলি সাব-কোয়েরি যা বাইরের ক্যোয়ারির উপর নির্ভর করে। এটি এসকিউএল এর জন্য লুপের মতো। উপ-ক্যোয়ারী বাইরের ক্যোয়ারিতে প্রতিটি সারির জন্য একবার চলবে:

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
)

5

সম্পাদনা: কিছুই নয়, কাসনসুইয়ের আরও ভাল উত্তর আছে।

এসকিউএল 2 কে এর জন্য এমন কিছু:

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

4

এই ক্যোয়ারীটি চালানোর জন্য আমার প্রিয় উপায়টি একটি অস্তিত্ব নেই with আমি বিশ্বাস করি এই ধরণের ক্যোয়ারি চালানোর জন্য এটি সবচেয়ে দক্ষ উপায়:

select o.OrderNumber,
       li.Quantity,
       li.Description
from Orders as o
inner join LineItems as li
on li.OrderID = o.OrderID
where not exists (
    select 1
    from LineItems as li_later
    where li_later.OrderID = o.OrderID
    and li_later.LineItemGUID > li.LineItemGUID
    )

তবে আমি এখানে প্রস্তাবিত অন্যান্য পদ্ধতির বিরুদ্ধে এই পদ্ধতিটি পরীক্ষা করি নি।


2

ক্রস চেষ্টা করে, সুন্দরভাবে কাজ করে তবে কিছুটা বেশি সময় নেয়। সজ্জিত লাইন কলামগুলিতে সর্বাধিক এবং যুক্ত গ্রুপ রয়েছে যা গতি বজায় রেখেছে এবং অতিরিক্ত রেকর্ড ফেলেছে।

সমন্বিত ক্যোয়ারী এখানে:

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

10
তবে দুটি কলামে পৃথকভাবে সর্বাধিক থাকা মানে পরিমাণটি বর্ণনার সাথে সম্পর্কিত নাও হতে পারে। যদি আদেশটি 2 টি উইজেট এবং 10 টি গ্যাজেট হয় তবে ক্যোয়ারীটি 10 ​​টি উইজেট ফেরত দেবে।
ব্রায়ানোরকা

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.