用于检查SQL Server中的组中是否存在确切ID(3+条记录)的逻辑

用于检查SQL Server中的组中是否存在确切ID(3+条记录)的逻辑,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有一些样本数据,如: INSERT INTO mytable ([FK_ID], [TYPE_ID]) VALUES (10, 1), (11, 1), (11, 2), (12, 1), (12, 2), (12, 3), (14, 1), (14, 2), (14, 3), (14, 4), (15, 1), (15, 2), (15, 4) 现在,我试图通过FK_ID检查每个组中1、2和3的TYPE_ID值是否完全匹配 因此,预期

我有一些样本数据,如:

INSERT INTO mytable
    ([FK_ID], [TYPE_ID])
VALUES
    (10, 1),
    (11, 1), (11, 2),    
    (12, 1), (12, 2), (12, 3),
    (14, 1), (14, 2), (14, 3), (14, 4),
    (15, 1), (15, 2), (15, 4)
现在,我试图通过FK_ID检查每个组中1、2和3的TYPE_ID值是否完全匹配

因此,预期输出如下所示:

10,1这应该失败 在FK_ID=10组中,我们只有一条记录 11,1,11,2这也应该失败 在FK_ID=11组中,我们有两条记录。 12,1,12,2,12,3这应该通过 在FK_ID=12组中,我们有两条记录。 所有类型的ID都与1、2和3的值完全匹配。 14,1,14,2,14,3,14,4这也应该失败 因为我们这里有4张唱片。 15,1,15,2,15,4这也应该失败 即使我们有三条记录,它也应该失败,因为这里的类型_ID 1、2、4与所需的匹配项1、2、3不匹配。 以下是我的尝试:

select * from mytable t1
where exists (select COUNT(t2.TYPE_ID) 
          from mytable t2 where t2.FK_ID = t1.FK_ID
          and t2.TYPE_ID IN (1, 2, 3)
          group by t2.FK_ID having COUNT(t2.TYPE_ID) = 3);
这并没有像预期的那样工作,因为它也传递给FK_ID=14,它有四条记录

演示:


此外,我们如何使其通用,以便如果我们需要检查4个或更多类型ID值,如1,2,3,4或1,2,3,4,5,我们可以通过更新几个值轻松完成这项工作。

以下查询将满足您的要求:

select fk_id
from t
group by fk_id
having sum(case when type_id in (1, 2, 3) then 1 else 0 end) = 3 and
       sum(case when type_id not in (1, 2, 3) then 1 else 0 end) = 0;
这假设您没有重复对,尽管这取决于您想要如何处理重复项,它可能与使用一样简单,从selectdistinct*fromt

至于一般性,您需要更新in列表和3

如果您想要更通用的东西:

with vals as (
      select id
      from (values (1), (2), (3)) v(id)
     )
select fk_id
from t
group by fk_id
having sum(case when type_id in (select id from vals) then 1 else 0 end) = (select count(*) from vals) and
       sum(case when type_id not in (select id from vals) then 1 else 0 end) = 0;
您可以使用以下代码:

SELECT y.fk_id FROM
    (SELECT x.fk_id, COUNT(x.type_id) AS count, SUM(x.type_id) AS sum 
    FROM mytable x GROUP BY (x.fk_id)) AS y
WHERE y.count = 3 AND y.sum = 6
为了使其通用,您可以将y.count与N相等,y.sum与N*N-1/2相等,其中N是您要查找的数字1,2,…,N.

您可以尝试此查询。计数和区分用于消除重复记录

SELECT 
    [FK_ID]
FROM 
    @mytable T 
GROUP BY 
    [FK_ID]
HAVING
    COUNT(DISTINCT CASE WHEN [TYPE_ID] IN (1,2,3) THEN [TYPE_ID] END) = 3
    AND COUNT(CASE WHEN [TYPE_ID] NOT IN (1,2,3) THEN [TYPE_ID] END) = 0
试试这个:

 select FK_ID,count(distinct TYPE_ID) from mytable
 where TYPE_ID<=3
 group by FK_ID
 having count(distinct TYPE_ID)=3
您应该将CTE与您在Q中提到的动态传递值一起使用

WITH CTE
     AS (
     SELECT FK_ID,
            COUNT(*) CNT
     FROM #mytable
     GROUP BY FK_ID
     HAVING COUNT(*) = 3) <----- Pass Value here What you want to Display Result,
     CTE1
     AS (
     SELECT T.[ID],
            T.[FK_ID],
            T.[TYPE_ID],
            ROW_NUMBER() OVER(PARTITION BY T.[FK_ID] ORDER BY
                             (
                                 SELECT NULL
                             )) RN
     FROM #mytable T
          INNER JOIN CTE C ON C.FK_ID = T.FK_ID),
     CTE2
     AS (
     SELECT C1.FK_ID
     FROM CTE1 C1
     GROUP BY C1.FK_ID
     HAVING SUM(C1.TYPE_ID) = SUM(C1.RN))
     SELECT TT1.*
     FROM CTE2 C2
          INNER JOIN #mytable TT1 ON TT1.FK_ID = C2.FK_ID;

请描述您想要的输出。我只需要FK_ID=12的记录,因为这些记录只符合3中提到的要求。这在:10,1,10,2,10,1?@P.Kouvarakis上不会成功吗。我最初是说没有重复的。我对答案进行了编辑,以解释如果存在重复项,该怎么办。如果使用from select distinct*from t,它还将匹配10,1,10,2,10,3,10,1您是否可以将和countdistinct type_id=3添加到having子句中?
ID  FK_ID   TYPE_ID
4   12      1
5   12      2
6   12      3