2015-07-31 3 views
0

Я пытаюсь написать запрос, который вернет мне строку на основе совпадения двух списков.SQL Compare Two Lists

У меня есть таблица с данными примера

ThreadId  EntityId 
1   50 
1   51 
2   50 
2   51 
2   52 
3   50 
3   53 

Я пытаюсь найти ThreadId где список EntityIds точно соответствует список идентификаторов я передаю в.

Пример результатов

ThreadId = 1 WHEN EntityIds IN (50, 51) 
ThreadId = 2 WHEN EntityIds IN (50, 51, 52) 
ThreadId = 3 WHEN EntityIds IN (50, 53) 
ThreadId = NULL WHEN EntityIds IN (50, 52) -- NULL because there is no thread with just these two EntityIds 

Любая помощь была бы принята с благодарностью.

Заранее спасибо

Нил

+0

Возможно, я не понимаю вопроса, но вы хотите, чтобы какой-то код, который принимает список идентификаторов сущностей, сопоставляет его с таблицей и возвращает идентификатор потока, если есть совпадение? –

+0

Привет, Робби, да, это точно правильно – NeilT

+0

Как будет представлен список ввода - как параметр SP или в таблице? –

ответ

0

Я думаю, что вы хотите что-то вроде этого:

CREATE PROCEDURE [dbo].[Matcher] 
    @Source AS SourceType READONLY 
AS 
    BEGIN 

     DECLARE @RetVal INT; 

     DECLARE @MatchString VARCHAR(MAX); 

     DECLARE @TargetSet TABLE 
      (
       threadid INT , 
       entities VARCHAR(MAX) , 
       processed BIT DEFAULT 0 
      ); 

     DECLARE @newcsv VARCHAR(MAX); 

     DECLARE @currentthread INT; 

     INSERT INTO @TargetSet 
       (threadid 
       ) 
       SELECT DISTINCT 
         threadid 
       FROM TheData; 

     -- Flatten the source string 

     SET @MatchString = (SELECT SUBSTRING((SELECT ',' 
                 + CAST(s.EntityId AS VARCHAR) 
               FROM @Source s 
               ORDER BY s.EntityId 
               FOR 
               XML PATH('') 
              ), 2, 200000) AS CSV 
          );  

     -- Flatten the target data 

     WHILE (SELECT COUNT(*) 
       FROM @TargetSet 
       WHERE processed = 0 
      ) > 0 
      BEGIN 

       SET @currentthread = (SELECT TOP 1 
               threadid 
             FROM  @TargetSet 
             WHERE processed = 0 
            ); 

       SET @newcsv = (SELECT SUBSTRING((SELECT ',' 
                  + CAST(EntityId AS VARCHAR) 
                FROM TheData 
                WHERE ThreadId = @currentthread 
                ORDER BY EntityId 
                FOR 
                XML PATH('') 
               ), 2, 200000) AS CSV 
          ); 

       UPDATE @TargetSet 
       SET  entities = @newcsv , 
         processed = 1 
       WHERE threadid = @currentthread; 

      END; 

     -- Perform the match 

     SET @RetVal = (SELECT threadid 
         FROM @TargetSet 
         WHERE entities = @MatchString 
        );    

     SELECT @RetVal; 

    END; 

Я поднял таблицу -> CSV код из here, но есть много других примеров, пиная вокруг сети, если это не займет ваш фантазии.

+0

Спасибо, Робби, отлично работает! – NeilT

1

Вы можете сделать это с group by и having. Если вы хотите точный матч:

select threadid 
from threadentitys 
group by threadid 
having sum(case when entityid in (1, 2, 3) then 1 else 0 end) = 3 and 
     sum(case when entityid not in (1, 2, 3) then 1 else 0 end) = 0; 

Первое условие подсчитывает количество матчей. «3» говорит, что есть три матча - которые (при отсутствии дубликатов в таблице) означают, что все совпадают. Второй говорит, что никакие другие объекты не совпадают.