2011-08-18 6 views
3

동일한 주문을 한 고객을 찾아야합니다. OrderID를 1, 3 명령이 동일한 것으로 간주동일한 주문을 가진 고객 찾기

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

(하여 T-SQL)

주문

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

OrderLine에 때문에 orderlines의 숫자 "주문 "및"참조 "는 두 주문 모두 동일합니다. 고객 2와 6이 동일한 주문을했음을 의미합니다.

주문 5는 수량이 다르기 때문에 주문 1 및 3과 동일하지 않습니다.

주문 2는 주문 순서가 다르기 때문에 주문 6과 동일하지 않습니다.

주문 4와 7도 동일합니다.

IdenticalOrders

OrderID CustomeerID 
1 2 
3 6 
4 2 
7 8 

그것은 쉬운 일처럼 보이지만 어디서부터 시작 난 그냥 이해할 수 없다 :

나는이 같은 ressult 검색하고 있습니다. (전 아직 t-SQL에 익숙하지 않습니다 :-))

+1

스케치 할 때 다른 순서와 동일한 순서를 제공하지만 어느 것이 일치하는 순서인지 알 수 없습니다. – devio

+1

이것은 관계형의 변형입니다. –

+0

나는 devio에 동의합니다. 결과 정보는 전혀 유용하지 않습니다. 특히 일치하는 주문이 2 개 이상인 경우 특히 그렇습니다. 나는 마틴 스미스의 두 번째 옵션 (나는 훌륭하다고 생각한다)의 변형을 생각해 냈다. 나는 그것을 곧 게시 할 것이다. – deutschZuid

답변

0

을 설정 JOIN 다음 GROUP_CONCAT을 시뮬레이션 XML PATH를 사용할 수 있습니다. 반복없이 일치하는 모든 조합이 표시됩니다.

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

또한이 개 결과는이 마틴의 두 번째 제안의 확장

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

결과는 'Invoice와 동일합니다. 11' –

+0

SQL 활동으로 인해 항상 고려해야 할 성능 문제가 있습니다. 명시된 요구 사항 때문에 내 코드를 사용하여 Invoice 체크섬을 생성하고 해당 값을 Invoices 테이블에 저장하는 것이 좋습니다. 이렇게하면 주문을 제출할 때마다 다시 계산할 필요가 없습니다. Invoices.ItemsCheckSum 열에 대한 빠른 수행 만하면됩니다 (훨씬 더 효율적입니다). 그러나 이것은 단지 권고 일뿐입니다. 당신은 당신 자신의 개발자입니다. 내 코드도 이와 같은 열없이 작동합니다. –

+0

고마워요 .--) 이것에 대해 살펴 보겠습니다. 두 솔루션을 모두 테스트 해 보겠습니다. – David

관련 문제