通过仅在一个语句中检查组的条件来过滤行

时间:2013-07-14 11:19:19

标签: sql sql-server tsql

我有以下声明:

SELECT
    (CONVERT(VARCHAR(10), f1, 120)) AS ff1,
    CONVERT(VARCHAR(10), f2, 103) AS ff2,
    ...,
    Bonus,
    Malus,
    ClientID,
FROM 
    my_table                        
WHERE
    <my_conditions>
ORDER BY 
    f1 ASC

此select为每个ClientID返回多行。我必须使用没有任何非空Bonus或Malus行的客户端过滤掉所有行。

如何通过仅一个语句更改此选项而不重复所有选择来完成此操作?

我可以将结果存储在#temp_table中,然后对数据进行分组并使用分组结果来过滤临时表。 - 但我应该只用一个声明

我可以执行此选择两次 - 一次对其进行分组,然后我可以根据分组结果过滤行。 但我不想两次选择

可能CTE(公用表格表达式)在这里可以用来执行一次选择,并且能够使用结果进行分组,然后根据分组结果选择所需的结果。

这个问题有更优雅的解决方案吗?

提前谢谢!

为了澄清SQL应该做什么,我添加一个例子:

ClientID  Bonus  Malus
1         1      
1                
1                1
2                
2                
3         4      
3                5
3         1      

因此,在这种情况下,我不希望出现ClientID = 2行(它们不是很有趣)。结果应该是:

ClientID  Bonus  Malus
1         1      
1                
1                1
3         4      
3                5
3         1      

3 个答案:

答案 0 :(得分:0)

SELECT Bonus,
       Malus,
       ClientID
FROM my_table                        
WHERE ClientID not in 
(
  select ClientID
  from my_table
  group by ClientID
  having count(Bonus) = 0 and count(Malus) = 0
)

答案 1 :(得分:0)

CTE可以正常工作,但实际上它的内容将被执行两次,因为它们被克隆到使用CTE的所有地方。与使用临时表相比,这可以是净性能赢或输。如果查询非常昂贵,它可能会失败。如果它很便宜或者返回了很多行,临时表将失去比较。

哪种解决方案更好?查看执行计划并衡量绩效。

CTE是更容易,更易于维护的更少冗余的替代方案。

答案 2 :(得分:0)

您尚未指定Bonus和Malus列的数据类型。因此,如果它们是整数(或可以转换为整数),那么下面的查询应该会有所帮助。它计算每个ClientID的两列总和。这些总和对于同一客户端的每个细节行都是相同的,因此我们可以在WHERE条件下使用它们。语句SUM() OVER()被称为“窗口函数”,不能在WHERE子句中使用,因此我必须仅仅因为语法而将您的选择列表包装为父类。

SELECT *
FROM (
    SELECT
        CONVERT(VARCHAR(10), f1, 120) AS ff1,
        CONVERT(VARCHAR(10), f2, 103) AS ff2,
        ...,
        Bonus,
        Malus,
        ClientID,
        SUM(Bonus) OVER (PARTITION BY ClientID) AS ClientBonusTotal,
        SUM(Malus) OVER (PARTITION BY ClientID) AS ClientMalusTotal
    FROM 
        my_table                        
    WHERE
        <my_conditions>
) a
WHERE ISNULL(a.ClientBonusTotal, 0) <> 0 OR ISNULL(a.ClientMalusTotal, 0) <> 0
ORDER BY f1 ASC
相关问题