Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 通过仅在一条语句中检查组的条件来筛选行_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 通过仅在一条语句中检查组的条件来筛选行

Sql 通过仅在一条语句中检查组的条件来筛选行,sql,sql-server,tsql,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
    (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
因此,在本例中,我不希望ClientID=2行看起来不有趣。结果应该是:

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

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

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


CTE是更简单、更易维护、冗余更少的替代方案。

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

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

我必须过滤掉所有客户的行,这些客户没有任何带有非空奖金或马吕斯的行。你能把它换成你想要的而不是你不想要的吗?这句话让我头疼:对不起:。我将添加一个例子来更好地解释它。问题中有一个例子。请让我知道是否需要更多的澄清。这正是我不想做的。请看我问题中的粗体文本-选择两次,我有很多复杂的条件,你的复杂条件只需要在外部选择。内部select只有having子句。我对CTEs有些感觉。它们不仅很好,而且非常出色,比自连接快50倍,比光标快100倍。。我对表演也不夸张。。即使他们克隆了两次,我也会支持CTE。。仍然比下一个最好的快25倍alternative@user1974729它们的执行方式与通过手动将CTE定义复制到所有使用CTE定义的地方而获得的查询相同。SQLServer在内部正是这样做的。通常这就是你想要的:
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
)
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