2017-06-15 74 views
1

我正在SQL Server 2008数据库上运行2个报表。父表是帐户,子表是合同,并且它们在唯一标识符字段 - 帐户ID上链接。SQL添加额外的子查询以排除主要查询的结果

我的目标是根据什么类型的合同提供所有账户和合同。

我有这个疑问现在:

Select Account.*, C.* from Account 

Left Join Contracts C 
on C.AccountID=Account.AccountId 

Where 

(Case when C.T1 = 'TYPE1' or C.T1 = 'TYPE2' or C.T1 = 'TYPE3' or C.T1 = 'TYPE4' or C.T1 = 'TYPE5' or C.T1 = 'TYPE6' Then 0 Else 1 END) = 0 
and EXISTS (Select E.AccountID, E.T1 from Contracts E Where E.AccountID = C.AccountID and (E.T1 LIKE 'TYPE6' and Convert(Date,E.End_Date) = Convert(Date,C.End_Date))) 

Order by Account.AccountID 

的想法是拉有合同的所有帐户,其中T1 = TYPE1-6,但前提是他们有合同在哪里T1 = TYPE6。这给出的结果是这样的:

AccountID Contract T1 
    1    1  4 
    1    2  5 
    1    3  6 

    2    4  6 
    2    5  2 
    2    6  6 

    3    7  6 
    3    8  6 
    3    9  6 

我从这个需要接下来的事情是,它排除只有合同TYPE6帐户,我完全失去了。理想的结果是,我将获得帐户1 & 2的所有3份合同,但会从结果中删除帐户3。

我的假设是,我将需要一个额外的查询,给我我不想要的结果。我不完全理解EXCEPT语句,但我觉得可能需要放在这里吗?

该查询给了我所有的帐户/合同不应该包括在我的第一个结果:

Select Account.*, C.* from Account 

Left Join Contracts C 
on C.AccountID=Account.AccountId 

where 
(Case When C.T1 = 'TYPE6' Then 0 Else 1 End) = 0 
and NOT EXISTS (Select E.AccountID, E.T1 from Contracts E Where E.AccountID = C.AccountID and E.T1 NOT LIKE '%TYPE6%'and Convert(Date,E.End_Date) = Convert(Date,C.End_Date)) 


Order by Account.AccountID 

有没有办法对我说“从第一查询给我的一切,但排除一切从第二?'

此外任何清理我的言论的意见,将不胜感激。我并不是自称擅长这一点。

谢谢!

+1

喜并欢迎来到SO。我们需要一些细节以帮助更多。这里是一个开始的好地方。 http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/ –

+0

我不明白为什么帐户2在您的结果中。它不符合你的标准,“但只有当他们有一个合同在哪里T1 = TYPE6”。帐户2只有类型1,2和3.没有类型6. –

+0

@SeanLange这是我可以给的所有信息。我无法给你任何样本数据。 – Brennen

回答

0

最后一个条件应该做的伎俩与另一合同的存在的测试,是不是6类的(我没有在本地测试)

Select Account.*, C.* from Account 

     Left Join Contracts C 
     on C.AccountID=Account.AccountId 

     Where 

     (Case when C.T1 = 'TYPE1' or C.T1 = 'TYPE2' or C.T1 = 'TYPE3' or C.T1 = 'TYPE4' or C.T1 = 'TYPE5' or C.T1 = 'TYPE6' Then 0 Else 1 END) = 0 
     and EXISTS (Select E.AccountID, E.T1 from Contracts E Where E.AccountID = C.AccountID and (E.T1 LIKE 'TYPE6' and Convert(Date,E.End_Date) = Convert(Date,C.End_Date))) 
    AND (C.T1 <> 'TYPE6' OR EXISTS(SELECT * FROM Contracts con WHERE con.AccountId = Account.AccountId AND con.T1 <> 'TYPE6')) 

     Order by Account.AccountID 
+0

感谢您的回答。不幸的是,这不适用于有一份TYPE6合同的帐户,但它确实让我更接近! – Brennen

0

你想上的帐户信息(无论是任何或所有它的记录是类型6)。所以按帐户ID进行分组并检查您的帐户。

select accountid 
from contracts 
where t1 between 1 and 6 
group by accountid 
having count(case when t1 = 6 then 1 end) > 0 -- at least one record of type 6 
    and count(case when t1 <> 6 then 1 end) > 0 -- at least one record of type 1 to 5 

然后,您可以选择这些帐户的记录:

select * 
from accounts a 
join contracts c on c.accountid = a.accountid 
where c.t1 between 1 and 6 and c.accountid in (<above query>); 

,你读表一次使用,而不是COUNT解析函数COUNT OVER一种替代方案:

select accountid, contract, t1 
from 
(
    select 
    a.*, c.*, 
    count(case when c.t1 = 6 then 1 end) over (partition by c.accountid) as c6, 
    count(case when c.t1 <> 6 then 1 end) over (partition by c.accountid) as c12345 
    from accounts a 
    join contracts c on c.accountid = a.accountid 
    where c.t1 between 1 and 6 
) mydata 
where c6 > 0 and c12345 > 0; 
+0

在你的例子中,你选择的所有列都存在于'contracts'中。如果您确实不想从'accounts'获得更多数据,请从上述查询中移除该表。 –