2011-08-18 47 views
3

我需要找到訂單完全相同的客戶。 (使用T-SQL)查找具有相同訂單的客戶

訂單

OrderID Customerer 
1 2 
2 5 
3 6 
4 2 
5 4 
6 6 
7 8 

訂單行

OrderLineID OrderID OrderDate OrderType Quantity Reference 
1 1 01/01/2011 1 1 Coca Cola 
2 1 01/01/2011 1 3 Tea 
3 2 02/02/2011 2 1 Coffee 
4 2 02/02/2011 2 2 Solo 
5 2 03/02/2011 1 1 Soda 
6 3 03/02/2011 1 3 Tea 
7 3 03/02/2011 1 1 Coca Cola 
8 4 05/06/2011 1 1 Beer 
9 5 06/06/2011 2 1 Tea 
10 5 06/06/2011 2 1 Coca Cola 
11 6 07/07/2011 1 1 Coffee 
12 6 07/07/2011 1 2 Solo 
13 6 07/07/2011 1 1 Soda 
14 6 07/07/2011 1 1 Beer 
15 7 08/08/2011 1 1 Beer 

在這裏與訂單ID 1和3的訂單被認爲是相同的,因爲對orderlines的數量,「數量「和」參考「在兩個訂單上都相同。這意味着客戶2和6已經下了相同的訂單。

訂單5與訂單1和3不同,因爲數量不同。

訂單2與訂單6不同,因爲訂單行不同。

4和7的順序也是相同的。

我正在尋找這樣的ressult:

IdenticalOrders

OrderID CustomeerID 
1 2 
3 6 
4 2 
7 8 

這似乎是一件容易的事,但我只是不明白從哪裏開始。 (我還是t-sql的新手:-))

+1

您草擬它的結果會爲您提供與其他任何訂單相同的任何訂單,但您不會知道哪個是匹配訂單 – devio

+1

這是關係部門的一個變體。 –

+0

我同意devio。由此產生的信息根本沒有用處,特別是如果有超過2個匹配的訂單。我想出了馬丁史密斯的第二種選擇(我認爲它很棒)的一個變種。我會盡快發佈。 – deutschZuid

回答

0

這是馬丁的第二個建議的延伸。這將顯示所有匹配的組合,不會有任何重複。

;With FmtOL(customer, orderid, complete_order) as 
(   
SELECT customer, orderid, complete_order 
    FROM Order O 
        cross apply (SELECT CAST(Quantity AS VARCHAR(30)) 
              + '~' + Reference + '~~' 
            FROM  OrderLine OL 
            WHERE  OL.OrderID = O.OrderID 
            ORDER BY Reference , 
              Quantity 
           FOR 
            XML PATH('') 
           ) T (complete_order) 
) 
SELECT T1.OrderId, 
     T1.Customer, 
     STUFF(C1.a, 1, 2, '') as [SameAs] 
FROM FmtOL T1 
Cross apply (SELECT '; ' + 'Customer ' + Cast(T2.Customer as varchar(30)) 
        + '''s order ' + Cast(T2.OrderID as varchar(30)) 
       FROM FmtOL T2 
       WHERE T1.Customer < T2.Customer 
        AND T1.OrderId < T2.OrderId 
        AND T1.complete_order = T2.complete_order 
       order by ';' + Cast(T2.Customer as varchar(30)) 
        + '''s order ' + Cast(T2.OrderID as varchar(30)) 
        , t2.orderid 
       for xml path('') 
      ) C1 (a) 
    where C1.a is not null 

結果應該是這樣的:

OrderId Customer SameAs 
1  2  Customer 6's order 3 
4  2  Customer 8's order 7 
2

下面是一種方法。

SELECT O1.OrderID , 
     O1.Customer , 
     O2.OrderID , 
     O2.Customer 
FROM [Order] O1 
     JOIN [Order] O2 ON O1.OrderID < O2.OrderID 
          AND O1.Customer <> O2.Customer 
WHERE NOT EXISTS (SELECT Quantity , 
          Reference 
        FROM OrderLine 
        WHERE O1.OrderID = OrderLine.OrderID 
        EXCEPT 
        SELECT Quantity , 
          Reference 
        FROM OrderLine 
        WHERE O2.OrderID = OrderLine.OrderID) 
     AND NOT EXISTS (SELECT Quantity , 
           Reference 
         FROM OrderLine 
         WHERE O2.OrderID = OrderLine.OrderID 
         EXCEPT 
         SELECT Quantity , 
           Reference 
         FROM OrderLine 
         WHERE O1.OrderID = OrderLine.OrderID) 

您還可以使用XML PATH模擬GROUP_CONCAT然後JOIN兩個結果集

DECLARE @T TABLE 
    (
     OrderId INT PRIMARY KEY, 
     Customer INT , 
     complete_order VARCHAR(MAX) 
    ) 

    INSERT INTO @T 
      SELECT * 
      FROM [Order] O 
        CROSS APPLY (SELECT CAST(Quantity AS VARCHAR(30)) 
              + '~' + Reference + '~~' 
            FROM  OrderLine OL 
            WHERE  OL.OrderID = O.OrderID 
            ORDER BY Reference , 
              Quantity 
           FOR 
            XML PATH('') 
           ) T (complete_order) 

SELECT T1.OrderId, 
     T1.Customer 
FROM @T T1 
WHERE EXISTS (SELECT * 
       FROM @T T2 
       WHERE T1.Customer <> T2.Customer 
         AND T1.OrderId <> T2.OrderId 
         AND T1.complete_order = T2.complete_order) 
0

這是最簡單的方法。

-- sample table 
create table x 
    (
     LineId int identity(1, 1) 
     ,InvoiceFk int 
     ,ProductFk int 
     ,Quantity int 
    ) 

-- sample data 
insert into x 
(InvoiceFk, ProductFk, Quantity) values 
    (11, 1, 1) 
    ,(11, 2, 1) 
    ,(11, 3, 1) 
    ,(12, 1, 2) 
    ,(12, 2, 2) 
    ,(12, 3, 2) 
    ,(13, 1, 3) 
    ,(13, 2, 3) 
    ,(13, 3, 3) 

-- your order, probably from a parameter 
declare @order table 
    (
     InvoiceFk int 
     ,ProductFk int 
     ,Quantity int 
    ) 
insert into @order 
(InvoiceFk, ProductFk, Quantity) values 
    (14, 1, 1) -- duplicate invoice 11 
    ,(14, 2, 1) 
    ,(14, 3, 1) 

-- your order unique checksum 
declare @orderCheck int 
select @orderCheck = checksum_agg(checksum(ProductFk, Quantity)) 
from @order 

-- test your order in existing data 
declare @match int 
select @match = 
    (
     select TOP 1 InvoiceFk from 
     (
      select 
       InvoiceFk 
       ,checksum_agg(Col1) as Col2 
      from 
       (
       select 
        InvoiceFk 
        ,checksum(productfk, quantity) as Col1 
       from x 
       ) as T1 
      group by 
       InvoiceFk 
     ) as T2 
     where 
      T2.Col2 = @orderCheck 
    ) 


-- evaluate if your order is unique or not 
if (@match is not null) 
begin 
    print 'Identical to invoice: ' + Str(@match); 
end 
else 
begin 
    print 'Order is unique'; 
end 

-- clean up sample table 
drop table x  

祝你好運!

+0

結果與'與發票相同:11' –

+0

任何SQL活動都會遇到性能問題。由於您聲明的要求,我建議您使用我的代碼生成發票校驗和並將該值存儲在發票表中。這樣,每次嘗試提交訂單時都不需要重新計算它。您需要做的只是在Invoices.ItemsCheckSum列中進行快速WHERE(這將更加有效)。但這只是一個建議。你是你自己的開發者。我的代碼也沒有這樣的列。 –

+0

謝謝:-)我會研究這一點。我會測試這兩種解決方案。 – David

相關問題