【问题标题】:SQL How to get 0 valuesSQL如何获得0个值
【发布时间】:2011-01-18 04:04:19
【问题描述】:

我正在使用此 SQL 生成下面的图表 (RS2008R2):

SELECT  Merchant.Name as MerchantName, 
    CONVERT(char(8), 
    VoucherRedemption.RedeemedAtUTC, 112) as ShortDateRedeemed,
    COUNT(CONVERT(char(8), VoucherRedemption.RedeemedAtUTC, 112)) as NumberRemeemedOnDay
FROM    Merchant 
INNER JOIN  Terminal ON Merchant.MerchantUID = Terminal.MerchantUID 
INNER JOIN  VoucherRedemption ON Terminal.TerminalUID = VoucherRedemption.TerminalUID
WHERE       Merchant.Name = 'Merchant 1'
GROUP BY    merchant.Name, 
            CONVERT(char(8), VoucherRedemption.RedeemedAtUTC, 112)

问题:如何在图表的底轴上获得稳定的日期时间线?即我想在此图中显示很多 0 列数据,并显示所有日期。

虽然 Reporting Services 2008R2 可以很好地处理这个问题,但还没有找到一个很好的例子。

【问题讨论】:

    标签: sql reporting-services


    【解决方案1】:

    零值通过从要显示零值的表的左连接来显示。例如,以下将显示零值:

    SELECT Users.name, COUNT(UserLoginHistory.*) AS Logins
    FROM Users
    INNER JOIN UserLoginHistory ON Users.id = UserLoginHistory.user_id
    GROUP BY Users.name
    

    而以下

    SELECT Users.name, COUNT(UserLoginHistory.*) AS Logins
    FROM Users
    LEFT JOIN UserLoginHistory ON Users.id = UserLoginHistory.user_id
    GROUP BY Users.name
    

    在这种情况下,您希望显示零值的日期,所以它有点棘手。您可能需要创建一个表或视图,其中包含要显示的日期列表,然后将其连接到您的数据中。根据您的要求,检索数据集后,在 SQL 之外执行此操作可能会更容易。

    【讨论】:

    • 那不是语法错误吗? count(tbl.*) 无效。使用 count(UserLoginHistory.user_id) 代替
    • 取决于您的 DBMS,但 COUNT(UserLoginHistory.user_id) 也可以解决问题!
    【解决方案2】:

    首先,您的查询可以写得更简单

    SELECT  Merchant.Name as MerchantName, 
        CONVERT(char(8), VoucherRedemption.RedeemedAtUTC, 112) as ShortDateRedeemed,
        COUNT(VoucherRedemption.RedeemedAtUTC) as NumberRemeemedOnDay
    FROM    Merchant 
    INNER JOIN  Terminal ON Merchant.MerchantUID = Terminal.MerchantUID 
    INNER JOIN  VoucherRedemption ON Terminal.TerminalUID = VoucherRedemption.TerminalUID
    WHERE       Merchant.Name = 'Merchant 1'
    GROUP BY    merchant.Name,  VoucherRedemption.RedeemedAtUTC
    

    最终的解决方案是

    ;with tmp as (
        SELECT  Merchant.Name as MerchantName, 
            VoucherRedemption.RedeemedAtUTC as ShortDateRedeemed,
            COUNT(VoucherRedemption.RedeemedAtUTC) as NumberRemeemedOnDay
        FROM    Merchant 
        INNER JOIN  Terminal ON Merchant.MerchantUID = Terminal.MerchantUID 
        INNER JOIN  VoucherRedemption ON Terminal.TerminalUID = VoucherRedemption.TerminalUID
        WHERE       Merchant.Name = 'Merchant 1'
        GROUP BY    merchant.Name,  VoucherRedemption.RedeemedAtUTC
    ), dates as (
        select min(ShortDateRedeemed) theDate, max(ShortDateRedeemed) endDate
        from tmp
        union all
        select theDate + 1, endDate
        from dates
        where theDate < endDate
    )
    SELECT  A.MerchantName, 
            CONVERT(char(8), theDate, 112) as ShortDateRedeemed,
            isnull(A.NumberRemeemedOnDay,0)
    FROM dates B
    left join tmp A on B.theDate = A.ShortDateRedeemed
    

    【讨论】:

      【解决方案3】:

      可能有一种棘手的方法取决于您的 DBMS(例如 this one 表示一天中的某些时间),但我发现创建一个包含从 1 月 1 日开始的每个日期的表通常更容易,从 1900 年到 2999 年 12 月 31 日。我的特殊 Y3K 问题将通过我将死且无法照顾的事实得到解决:-)

      然后我将查询重组为该表与数据表本身的连接(或使用子查询和合并来消除 NULL),因此数据表中没有行的日期为零。

      【讨论】:

      猜你喜欢
      • 2015-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多