简体   繁体   中英

SQL How to get 0 values

I'm generating the graph below (RS2008R2) using this SQL:

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)

Question: How do I get a steady date timeline on the bottom axis of the graph? ie I want to show a lot of 0 column data in this graph with all dates showing.

A though is that Reporting Services 2008R2 may handle this well, but haven't found a good example yet.

替代文字

Zero values are shown by left joining from the table that you want to show zero values from. For example, the following will not show zero values:

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

whereas the following will :

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

In this case you want to show zero values for dates so it's a little trickier. You may need to create a table or view that has the list of dates you want to show then left join that to your data. Depending on your requirements, it may be easier to do this outside of SQL after you have retrieved the dataset.

There's probably a tricky way of doing this that depends on your DBMS (such as this one for times of the day) but I've found it's often easier just to create a table with every date in it from Jan 1, 1900 through to Dec 31, 2999. My particular Y3K problem will be fixed by the fact that I'll be dead and not very capable of caring :-)

Then I restructure my query as a join of that table against the data table itself (or with the use of sub-queries and coalesce to get rid of NULLs), hence dates with no rows in the data table get zero.

To begin with, your query can be written more simply

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

The final solution would be

;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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM