How to return a default value when no rows are returned from the select statement

前端 未结 7 1776
庸人自扰
庸人自扰 2021-01-22 13:26

I have a select statement that returns two columns, a date column, and a count(value) column. When the count(value) column doesn\'t have any records,

相关标签:
7条回答
  • 2021-01-22 13:48

    When you use a group by, it only creates a distinct list of values that exist in your records. Since 20140228 has no records, it will not show up in the group by.

    Your best bet is to generate a list of values, dates in your case, and left join or apply that table against your history table.

    I can't seem to copy my T-SQL in here so here's a hastebin.

    http://hastebin.com/winaqutego.vbs

    0 讨论(0)
  • 2021-01-22 13:50

    Try this:

    DECLARE @Records TABLE (
        [RecordDate] DATETIME,
        [RecordCount] INT
    )
    
    DECLARE @Date DATETIME = '02/26/2014' -- Enter whatever date you want to start with
    DECLARE @EndDate DATETIME = '03/31/2014' -- Enter whatever date you want to stop
    WHILE (1=1)
    BEGIN
        -- Insert the date into the temp table along with the count
        INSERT INTO @Records (RecordDate, RecordCount) 
        VALUES (CONVERT(VARCHAR(25), @Date, 101), 
                (SELECT COUNT(*) FROM dbo.YourTable WHERE RecordDate = @Date))
    
        -- Go to the next day
        @Date = DATEADD(d, 1, @Date)
    
        -- If we have surpassed the end date, break out of the loop
        IF (@Date > @EndDate) BREAK;
    END
    
    SELECT * FROM @Records
    

    If your dates have time components, you would need to modify this to check for start and end of day in the SELECT COUNT(*)... query.

    0 讨论(0)
  • 2021-01-22 13:56
    select convert(varchar(25), DateTime, 101) as recordDate,
           CASE WHEN count(value) =0 THEN 0 ELSE COUNT(value) END  recordCount
    from History
    where Value < 700
    group by convert(varchar(25), DateTime, 101)
    
    0 讨论(0)
  • 2021-01-22 13:56

    The best practice would be for you to have a datamart where a separate dimensional table for dates is kept with all dates you might be interested at - even if they lack amounts. DMason's answer shows the query with such a dimensional table.

    To keep with the best practices you would have a fact table where you'd keep these historical data already pre-grouped at the granularity level you need (daily, in this case), so you wouldn't need a GROUP BY unless you needed a coarser granularity (weekly, monthly, yearly).

    And in both your operational and datamart databases the dates would be stored as dates, not...

    But then, since this is real world and you might not be able to change what somebody else made... If you: a) only care about the dates that appear in [History], and b) such dates are never stored with hours/minutes; then following query might be what you'd need:

    SELECT MyDates.DateTime, COUNT(*)-1 AS RecordCount
    FROM (
          SELECT DISTINCT DateTime FROM History
       ) MyDates
    LEFT JOIN History H
      ON  MyDates.DateTime = H.Datetime
      AND H.Value < 700
    GROUP BY MyDates.DateTime
    

    Do try to add an index over DateTime and to further constrain the query with an earliest/latest date for better performance results.

    0 讨论(0)
  • 2021-01-22 14:04

    To generate rows for missing dates you can join your data to a date dimension table

    It would look something like this:

    select convert(varchar(25), ddt.DateField, 101) as recordDate,
           count(t.Value) as recordCount
    from History h
    right join dbo.DateDimensionTable ddt
        on ddt.DateField = convert(varchar(25), h.DateTime, 101)
    where h.Value < 700
    group by convert(varchar(25), h.DateTime, 101)
    

    If your table uses the DateTime column to store dates only (meaning the time is always midnight), then you can replace this

    right join dbo.DateDimensionTable ddt
        on ddt.DateField = convert(varchar(25), h.DateTime, 101)
    

    with this

    right join dbo.DateDimensionTable ddt
        on ddt.DateField = h.DateTime
    
    0 讨论(0)
  • 2021-01-22 14:09

    I agree that a Dates table (AKA time dimension) is the right solution, but there is a simpler option:

    SELECT
        CONVERT(VARCHAR(25), DateTime, 101) AS RecordDate,
        SUM(CASE WHEN Value < 700 THEN 1 ELSE 0 END) AS RecordCount
    FROM
        History
    GROUP BY
        CONVERT(VARCHAR(25), DateTime, 101)
    
    0 讨论(0)
提交回复
热议问题