如果所有类型相同,则SQL仅返回子行

时间:2016-07-12 17:09:19

标签: sql sql-server-2008

所以让我们从数据库设置开始:

"客户"表包含客户端。只有相关领域是:

Client.CLIENT

"策略"表包含具有3个相关字段的策略:

Policy.CLIENT
Policy.POLICY
Policy.CLASS

我需要返回一个策略列表,其中客户端具有多个策略,并且所有策略都是相同的策略类别。

例如,我们说有3类政策(A,B和C)。

  • 如果客户有3个策略,且所有策略都是类" A",则返回这些策略行。
  • 如果客户只有1个政策,请不要退回该行。
  • 如果客户有3个政策,但有两个是Class" A" 1是班级" B",不要返回任何行。

希望这是有道理的,如果不是,我可以扩展我的问题。

提前致谢!

3 个答案:

答案 0 :(得分:1)

select Policy.CLIENT 
from policy 
group by Policy.CLIENT 
having count(*) > 1 and count(distinct(Policy.class)) = 1


select Policy.CLIENT, policy.policy
from policy 
group by Policy.CLIENT, policy.policy 
having count(*) > 1 and count(distinct(Policy.class)) = 1

答案 1 :(得分:1)

这可以通过Gordon Linoff建议的方式完成,它应该是有效的。但是,如果你不是窗口函数的粉丝,这应该可以正常工作,并且也适用于其他SQL方言:

DECLARE @Client TABLE
(
  CLIENT_ID INT
  , CLIENT_NAME VARCHAR(10)
);

DECLARE @Policy TABLE
(
  CLIENT_ID INT
  , POLICY VARCHAR(10)
  , CLASS VARCHAR(1)
);

INSERT INTO @Client (CLIENT_ID, CLIENT_NAME)
VALUES (1, 'CLIENT 1')
  , (2, 'CLIENT 2')
  , (3, 'CLIENT 3');

INSERT INTO @Policy (CLIENT_ID, POLICY, CLASS)
VALUES (1, 'POLICY 1', 'A')
  , (1, 'POLICY 2', 'A')
  , (1, 'POLICY 3', 'A')
  , (2, 'POLICY 4', 'A')
  , (2, 'POLICY 5', 'A')
  , (2, 'POLICY 6', 'B')
  , (3, 'POLICY 7', 'A');

SELECT C.CLIENT_ID, C.CLIENT_NAME, P2.POLICY, P2.CLASS
FROM @Client AS C
INNER JOIN (
  SELECT CLIENT_ID
  FROM @Policy
  GROUP BY CLIENT_ID
  HAVING COUNT(DISTINCT CLASS) = 1
    AND COUNT(CLASS) > 1
    ) AS P
  ON P.CLIENT_ID = C.CLIENT_ID
INNER JOIN @Policy AS P2
  ON P2.CLIENT_ID = P.CLIENT_ID;

这就是结果:

CLIENT_ID CLIENT_NAME POLICY   CLASS 
--------- ----------- -------- ----- 
1         CLIENT 1    POLICY 1 A     
1         CLIENT 1    POLICY 2 A     
1         CLIENT 1    POLICY 3 A  
  • 客户端1有三个A政策,这就是它被带回的原因
  • 客户端2有两个A和一个B政策,因此不会带回来
  • 客户端3只有一个A政策 - 它没有带回来

查询data.stackexchange.com: https://data.stackexchange.com/stackoverflow/query/511200

可以对玩具有用

答案 2 :(得分:0)

如果您需要策略列表,则一个选项是窗口函数:

select p.*
from (select p.*,
             count(*) over (partition by p.client) as cnt,
             min(p.class) over (partition by p.client) as minc,
             max(p.class) over (partition by p.client) as maxc
      from policies p
     ) p
where cnt > 1 and minc <> maxc;