2016-07-03 4 views
2

ID 값 열 (테이블과 함께 일치 함)이있는 두 개의 테이블과 연결 값이 임의 순서로있는 연결 열이 있습니다. 두 열이 (순서에 관계없이) 정확히 동일한 항목을 포함하고 있는지 확인하고 비교하지 않을 경우 ID를 출력하는지 비교하고 싶습니다.SQL Server : 정렬되지 않은 집합이 동일하게 연결 된 열 비교

예 :

표 1

PersonID Products 
1   Apple|Pear|Orange 
2   Flour|Apple|Butter 
3   Apple 
4   Banana|Cashews 
5   Juice|Crackers|Banana|Cashews 
6   Cashews 

2

PersonID Products 
1   Orange|Apple|Pear 
2   Flour|Apple|Butter 
3   Apple|Banana 
4   Banana 
5   Crackers|Juice|Banana|Cashews 
6   Pear|Crackers 

난 제품은 표 1과 동일한 세트 (순서)되지 않은 모든 personids 얻을하고자 도표 따라서이 경우에는 사람 3 (추가 제품), 사람 4 (제품 누락) 및 사람 6 (다른 제품)입니다.

현재 주문이 다르게 주문 된 상품을 가지고 있기 때문에 현재 질문에서 사람 1과 5가 잘못 선택되었습니다.

나의 현재 쿼리는 다음과 같다 :

select t1.personid, t1.products as t1products, t2.products as t2products 
from table1 t1 (nolock) 
inner join table2 t2 (nolock) on t1.personid = t2.personid 
where t1.products != t2.products 

나는 또한 personid 당 여러 행에 미리 연결 형태로 데이터가 (각 제품 하나를 다시 별도로 두 개의 테이블), 그 경우 더 도움이됩니다 - 알파벳 순서로 연결하는 방법을 찾지 못했기 때문에 그 해결책이이 문제를 해결할 것입니다.

편집 (정화) 는 unconcatenated 데이터는 다음과 같다 :

표 2

PersonID Product 
1   Orange 
1   Apple 
1   Pear 
2   Flour 
2   Apple 
2   Butter 
3   Apple 
3   Banana 

표 1

PersonID Product 
1   Apple 
1   Pear 
1   Orange 
2   Flour 
2   Apple 
2   Butter 
3   Apple 

STUFF를 사용하여 PersonID로 연결했습니다.

+0

얼마나 많은 열이 그 길을 갈 것 인 경우 알파벳순으로 할 것을 필요가 있습니까? 몇 개의 열만있는 경우'>'또는'<'연산자를 사용하여 중첩 된'CASE' 문처럼 간단합니다. – ghg565

+0

구조는 제품이 아닌 여러 열로 구성되어 있으므로 작업 ID는 여러 행에서 반복됩니다. 1 ~ 300 개, 가장 일반적으로 각각 약 5-10 개 행이 가능합니다. – user3051065

답변

3

각 행에 대해 하나의 제품 양식으로 작성한 경우 반대표의 제품 및 개인 ID 모두에 대해 일치하지 않는 모든 결과를 조회 할 수 있습니다. 그런 다음 수행 결과를 다른 테이블과 노동 조합에 대해 동일합니다 : 당신은 선택과 CONCAT 결과이 포장 할 수

SELECT t1.personid, t1.product, '2' AS [Not Found In Table] 
FROM table1 t1 
LEFT JOIN table2 t2 ON t1.personid = t2.personid AND t1.product = t2.product 
WHERE t2.product IS NULL 
UNION 
SELECT t2.personid, t2.product, '1' AS [Not Found In Table] 
FROM table2 t2 
LEFT JOIN table1 t1 ON t2.personid = t1.personid AND t2.product = t1.product 
WHERE t1.product IS NULL 

당신에게 어떤 테이블에서 '아무튼 각 사람 누락 무엇의 좋은 목록을 공급하는 t 일치.

+0

이 솔루션은 제품의 순서를 고려합니다. 따라서 똑같은 제품을 가지고 있지만 순서가 다른 두 사람 ID는 결과 집합에 나타납니다/ –

+1

[나쁜 습관 : 모든 곳에 NOLOCK 올리기] (http://blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere /). –

+0

노 락백 코멘트 베이컨에 동의하지만, 그가 원래 쿼리에서 가지고있는 이유가 무엇인지 모르겠다. – ghg565

3

테스트 데이터

Declare @t1 TABLE (PersonID INT, Products Varchar(200)) 
INSERT INTO @t1 VALUES 
(1 ,'Apple|Pear|Orange'), 
(2 ,'Flour|Apple|Butter'), 
(3 ,'Apple'), 
(4 ,'Banana|Cashews'), 
(5 ,'Juice|Crackers|Banana|Cashews'), 
(6 ,'Cashews'); 

Declare @t2 TABLE (PersonID INT, Products Varchar(200)) 
INSERT INTO @t2 VALUES 
(1 ,'Orange|Apple|Pear'), 
(2 ,'Flour|Apple|Butter'), 
(3 ,'Apple|Banana'), 
(4 ,'Banana'), 
(5 ,'Crackers|Juice|Banana|Cashews'), 
(6 ,'Pear|Crackers'); 

쿼리

WITH Table1 AS (
SELECT PersonID 
     ,Split.a.value('.', 'VARCHAR(100)') Products 
FROM 
    (SELECT PersonID 
      ,Cast ('<X>' + Replace(Products, '|', '</X><X>') + '</X>' AS XML) AS Data 
    FROM @t1 
    ) AS t CROSS APPLY Data.nodes ('/X') AS Split(a) 
), Table2 AS (
SELECT PersonID 
     ,Split.a.value('.', 'VARCHAR(100)') Products 
FROM 
    (SELECT PersonID 
      ,Cast ('<X>' + Replace(Products, '|', '</X><X>') + '</X>' AS XML) AS Data 
    FROM @t2 
    ) AS t CROSS APPLY Data.nodes ('/X') AS Split(a) 
) 
SELECT t1.PersonID 
FROM Table1 t1 
WHERE NOT EXISTS (SELECT 1 
        FROM Table2 t2 
        WHERE t1.PersonID = t2.PersonID 
        AND t1.Products = t2.Products) 
UNION 
SELECT t2.PersonID 
FROM Table2 t2 
WHERE NOT EXISTS (SELECT 1 
        FROM Table1 t1 
        WHERE t1.PersonID = t2.PersonID 
        AND t1.Products = t2.Products) 
+0

그것은 데이터가 이미 행으로 분리되어있는 부분을 읽기 전에 내가 상상했던 것입니다. 누군가가 어려운 버전을했기 때문에 기쁩니다 :) – ghg565

1

은 단순히 전체 가입에 대한 행을 페어링하고있다. 이렇게하면 쌍이 표시되면 제품과 일치하고 그렇지 않으면 문제가 있음을 의미합니다. 그래서 나는이 간단한 쿼리는 문제를 해결할 수 있기를 바랍니다 : 제품의

SELECT DISTINCT PersonID FROM (
    SELECT * FROM table1 
    UNION ALL 
    SELECT * FROM table2 
) d 
GROUP BY PersonID, Products 
HAVING COUNT(*) != 2