Есть несколько способов сделать это. Вот как я это сделаю:
Сначала настройте данные:
DECLARE @Table1 AS TABLE (
id int,
l1 varchar(20)
) ;
INSERT INTO @Table1 VALUES
(1,'sun'),
(2,'shine'),
(3,'moon'),
(4,'light'),
(5,'earth'),
(6,'revolves'),
(7,'flow'),
(8,'fire'),
(9,'fighter'),
(10,'sun'),
(10,'shine'),
(11,'shine'),
(12,'moon'),
(1,'revolves'),
(10,'revolves'),
(2,'air'),
(3,'shine'),
(4,'fire'),
(5,'love'),
(6,'sun'),
(7,'rises') ;
Поскольку это известный список, установите «целевые» данные как их собственный набор. (В SQL таблицы почти всегда лучше работают, чем списки без правил. Ой, опечатка! Я имел в виду разделенные списки.)
DECLARE @Targets AS TABLE (
l2 varchar(20)
) ;
INSERT INTO @Targets VALUES
('sun'),
('moon'),
('earth') ;
ОПЕРАЦИЯ 1
получить все отдельные идентификаторы, которые имеют значения из списка 1
(солнце, луна, земля)
Достаточно просто с объединением:
SELECT Id
from @Table1 t1
inner join @Targets tg
on tg.l2 = t1.l1
ОПЕРАЦИЯ 2
получить все идентификаторы, count_of_list2_values, list2_values
на основе идентификаторов, которые мы получили от OPERATION1
Если я правильно следую желаемой логике, тогда (сначала прочитайте комментарии «присоединиться»):
SELECT
tt.Id
-- This next counts how many items in the Operation 1 list are not in the target list
-- (Spaced out, to make it easier to compare with the next line)
,sum( case when tg2.l2 is null then 1 else 0 end)
-- And this concatenates them together in a string (in later editions of SQL Server)
,string_agg(case when tg2.l2 is null then tt.l1 else null end, ', ')
from @Table1 tt
inner join (-- Operation 1 as a subquery, produce list of the Ids to work with
select t1.id
from @Table1 t1
inner join @Targets tg
on tg.l2 = t1.l1
) xx
on xx.id = tt.id
-- This is used to identify the target values vs. the non-target values
left outer join @Targets tg2
on tg2.l2 = tt.l1
-- Aggregate, because that's what we need to do
group by tt.Id
-- Order it, because why not?
order by tt.Id