मेरे पास दो टेबल हैं। एक है ट्रांजेक्शन टेबल और दूसरी है प्राइसबुक टेबल।

-Transaction Table-
|ItemID |   Assortment |UnitID|
|-------|--------------|------|
|A01    |           1  |ea    |
|A02    |           1  |kg    |
|A03    |           2  |pc    |

-PriceBook Table-
|ItemID |   Assortment  |UnitID |Price|
|-------|---------------|-------|-----|
|A01    |       1       |  ea   |1.5  |
|A02    |       1       |  pc   |2.5  |
|A03    |       2       |  kg   |5    |
|A03    |       2       |  pc   |1    |

मैं मूल्यपुस्तिका तालिका से मूल्य का चयन करना चाहता हूं, आइटम आईडी, वर्गीकरण और लेनदेन तालिका के साथ यूनिट आईडी से मेल खाता है। लेकिन यूनिटआईडी मैच वैकल्पिक है, इसलिए यदि यूनिटआईडी के साथ कोई मेल नहीं है, तो मैं केवल आइटम आईडी और वर्गीकरण के साथ मिलान परिणाम प्राप्त करना चाहता हूं।

-Result Table-
|ItemID|    UnitID| Price|
|------|----------|------|
|A01   |    ea    |1.5   |
|A02   |    pc    |2.5   |
|A03   |    pc    |1     |

मैं लेफ्ट आउटर जॉइन का उपयोग कर रहा हूं, लेकिन जब मैं आइटम आईडी और वर्गीकरण से मेल खाता हूं, तो मुझे आइटम ए03 के लिए दो पंक्तियां मिल रही हैं (मुझे केवल एक की आवश्यकता है), और यदि मैं आइटम आईडी, वर्गीकरण और यूनिट आईडी से मेल खा रहा हूं, तो मुझे आइटम ए02 के लिए शून्य मिल रहा है . मेरी क्वेरी निम्नलिखित है।

select DISTINCT Tx.ItemID, Pb.UnitID, Pb.Price
    from Transaction Tx with (nolock)
    LEFT OUTER JOIN PriceBook Pb With (NOLOCK)      
    ON Tx.ItemID = Pb.ItemID
    AND Tx.Assortment = Pb.Assortment
    AND Tx.UnitID = Pb.UnitID -- (This conditional should be optional)

मैं अपना वांछित परिणाम कैसे प्राप्त करूं?

0
sohaiby 13 जुलाई 2021, 10:30

3 जवाब

सबसे बढ़िया उत्तर

आप outer apply उन पंक्तियों के लिए जो अधिक स्तंभों से मेल नहीं खातीं:

with t(ItemID, Assortment, UnitID) as (
  select 'A01', 1, 'ea' union all
  select 'A02', 1, 'kg' union all
  select 'A03', 2, 'pc'
)
, pr(ItemID, Assortment, UnitID, Price) as (
  select 'A01', 1, 'ea', 1.5 union all
  select 'A02', 1, 'pc', 2.5 union all
  select 'A03', 2, 'kg', 5   union all
  select 'A03', 2, 'pc', 1
)
select
  t.itemid
  , t.assortment
  , coalesce(pr.unitid, pr2.unitid, t.unitid) as unitid
  , coalesce(pr.price, pr2.price) as price
from t
  left join pr
    on t.itemid = pr.itemid
      and t.assortment = pr.assortment
      and t.unitid = pr.unitid
  outer apply (
    select top 1 pr2.unitid, pr2.price
    from pr as pr2
    where t.itemid = pr2.itemid
      and t.assortment = pr2.assortment
      /*When no matches by unitid*/
      and pr.itemid is null
  ) as pr2
itemid | assortment | unitid | price
:----- | ---------: | :----- | ----:
A01    |          1 | ea     |   1.5
A02    |          1 | pc     |   2.5
A03    |          2 | pc     |   1.0

db<>fiddle यहां

3
astentx 13 जुलाई 2021, 07:56

यह apply के लिए बहुत अच्छा उपयोग-मामला है। हालांकि, अन्य उत्तरों की तुलना में सबसे अच्छा समाधान वास्तव में सरल है:

select t.ItemID, t.UnitID, pb.Price
from t outer apply
     (select top (1) pb.*
      from pb
      where pb.ItemID = t.ItemID and pb.Assortment = t.Assortment 
      order by (case when pb.UnitID = t.UnitId then 1 else 2 end)
     ) pb;

यहां एक db<>fiddle है।

कोई विंडो फ़ंक्शन नहीं। कोई अतिरिक्त जोड़ नहीं।

3
Gordon Linoff 13 जुलाई 2021, 11:22

एक outer apply row_number के साथ मिलकर आपको वांछित परिणाम दे सकता है; जहाँ कई पंक्तियाँ मेल खाती हैं, इस आधार पर प्राथमिकता दें कि क्या UnitId भी मेल खाता है:

select t.ItemID, t.UnitID, pb.Price
from t
outer apply (
    select price, UnitID, 
       Row_Number() over(order by case when pb.UnitID=t.UnitID then 1 end desc)pri
    from pb
    where pb.ItemID=t.ItemID and pb.Assortment=t.Assortment 
)pb
where pb.pri=1

देखें उदाहरण DB fiddle

2
Stu 13 जुलाई 2021, 08:50