如何按结果中未包含的列过滤GROUP BY查询中的结果?

时间:2019-04-13 18:38:15

标签: sql sql-server group-by

我得到以下结果:

results without filtering

通过此查询获得:

SELECT b.name, ISNULL(SUM(amount),0) AS 'Total', ISNULL(AVG(amount),0) AS 'Average'
FROM User_Transaction a
RIGHT OUTER JOIN Category b ON (a.category_id = b.category_id)
GROUP BY b.name

它包含用户已记录的所有金融交易的总数和平均值,而与记录交易的时间无关。

User_Transaction表中有一个datestamp列,我希望以此作为过滤条件。因此,我尝试以下操作:

SELECT b.name, ISNULL(SUM(amount),0) AS 'Total', ISNULL(AVG(amount),0) AS 'Average'
FROM User_Transaction a
RIGHT OUTER JOIN Category b ON (a.category_id = b.category_id)
WHERE 
 a.datestamp BETWEEN @date_from AND @date_to
GROUP BY b.name
ORDER BY b.name

这给了我

results with failed filtering

缺少OtherSalary条目,因为没有人使用这些名称进行过交易,因此没有要过滤的日期。

但是,我想包括这些名称,但它们的值仍为零。我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:2)

Ok, so essentially you want to list ALL Categories, and include Total and Average where such data is available in the specified time period?

If that is your intent, then read on!

First of all I reformatted the query to make it easier to understand the structure. I renamed the table alias for User_Tranaction from "a" to "ut", and the alias for Category from "b" to "cat"

SELECT 
    cat.name, 
    ISNULL(SUM(amount),0) AS 'Total', 
    ISNULL(AVG(amount),0) AS 'Average'
FROM 
    User_Transaction AS ut
    RIGHT OUTER JOIN Category AS cat 
        ON ut.category_id = cat.category_id
WHERE 
    ut.datestamp BETWEEN @date_from AND @date_to
GROUP BY 
    cat.name
ORDER BY 
    cat.name

To achieve the desired effect of listing all the categories, and only matching user transactuions in the time period, i have flipped the table join around to use a LEFT OUTER JOIN from Category to User_Transaction. In addition i have moved the date filtering to the ON clause of the join to User_Transaction. This has the effect of pre-filtering the data in User_Transactions before the resulting data is linked to the Category data.

SELECT 
    cat.name, 
    ISNULL(SUM(amount),0) AS 'Total', 
    ISNULL(AVG(amount),0) AS 'Average'
FROM 
    Category AS cat
    LEFT OUTER JOIN User_Transaction AS ut
        ON cat.category_id = ut.category_id
        AND ut.datestamp BETWEEN @date_from AND @date_to
GROUP BY 
    cat.name
ORDER BY 
    cat.name

Hope that helps.

答案 1 :(得分:1)

在这里走

SELECT c.name, ISNULL(SUM(amount),0) AS 'Total', ISNULL(AVG(amount),0) AS 'Average'
FROM User_Transaction ut
RIGHT OUTER JOIN Category c ON (ut.category_id = c.category_id)
WHERE 
    (ut.datestamp BETWEEN @date_from AND @date_to) OR ut.datestamp IS NULL
GROUP BY c.name
ORDER BY c.name

答案 2 :(得分:1)

尝试将OR a.datestamp IS NULL添加到where条件:

SELECT b.name, ISNULL(SUM(amount),0) AS 'Total', ISNULL(AVG(amount),0) AS 'Average'
FROM User_Transaction a
RIGHT OUTER JOIN Category b ON (a.category_id = b.category_id)
WHERE 
 a.datestamp BETWEEN @date_from AND @date_to OR a.datestamp IS NULL
GROUP BY b.name
ORDER BY b.name

答案 3 :(得分:0)

我认为它将与UNION一起使用:首先提出您的请求,然后在UNION的第二部分中选择没有日期可过滤的条目。它应该像这样