How to set a default row for a query that returns no rows?

后端 未结 11 1425
青春惊慌失措
青春惊慌失措 2020-12-03 06:43

I need to know how to return a default row if no rows exist in a table. What would be the best way to do this? I\'m only returning a single column from this particular table

相关标签:
11条回答
  • 2020-12-03 06:58

    One approach for Oracle:

    SELECT val
    FROM myTable
    UNION ALL
    SELECT 'DEFAULT'
    FROM dual
    WHERE NOT EXISTS (SELECT * FROM myTable)
    

    Or alternatively in Oracle:

    SELECT NVL(MIN(val), 'DEFAULT')
    FROM myTable
    

    Or alternatively in SqlServer:

    SELECT ISNULL(MIN(val), 'DEFAULT')
    FROM myTable
    

    These use the fact that MIN() returns NULL when there are no rows.

    0 讨论(0)
  • 2020-12-03 06:59

    I figured it out, and it should also work for other systems too. It's a variation of WW's answer.

    select rate 
    from d_payment_index
    where fy = 2007
      and payment_year = 2008
      and program_id = 18
    union
    select 0 as rate 
    from d_payment_index 
    where not exists( select rate 
                      from d_payment_index
                      where fy = 2007
                        and payment_year = 2008
                        and program_id = 18 )
    
    0 讨论(0)
  • 2020-12-03 07:01

    One table scan method using a left join from defaults to actuals:

    CREATE TABLE [stackoverflow-285666] (k int, val varchar(255))
    
    INSERT  INTO [stackoverflow-285666]
    VALUES  (1, '1-1')
    INSERT  INTO [stackoverflow-285666]
    VALUES  (1, '1-2')
    INSERT  INTO [stackoverflow-285666]
    VALUES  (1, '1-3')
    INSERT  INTO [stackoverflow-285666]
    VALUES  (2, '2-1')
    INSERT  INTO [stackoverflow-285666]
    VALUES  (2, '2-2')
    
    DECLARE @k AS int
    SET @k = 0
    
    WHILE @k < 3
        BEGIN
            SELECT  @k AS k
                   ,COALESCE(ActualValue, DefaultValue) AS [Value]
            FROM    (
                     SELECT 'DefaultValue' AS DefaultValue
                    ) AS Defaults
            LEFT JOIN (
                       SELECT   val AS ActualValue
                       FROM     [stackoverflow-285666]
                       WHERE    k = @k
                      ) AS [Values]
                    ON 1 = 1
    
            SET @k = @k + 1
        END
    
    DROP TABLE [stackoverflow-285666]
    

    Gives output:

    k           Value
    ----------- ------------
    0           DefaultValue
    
    k           Value
    ----------- ------------
    1           1-1
    1           1-2
    1           1-3
    
    k           Value
    ----------- ------------
    2           2-1
    2           2-2
    
    0 讨论(0)
  • 2020-12-03 07:03

    This would be eliminate the select query from running twice and be better for performance:

    Declare @rate int
    
    select 
        @rate = rate 
    from 
        d_payment_index
    where 
        fy = 2007
        and payment_year = 2008
        and program_id = 18
    
    IF @@rowcount = 0
        Set @rate = 0
    
    Select @rate 'rate'
    
    0 讨论(0)
  • 2020-12-03 07:03

    How about this:

    SELECT DEF.Rate, ACTUAL.Rate, COALESCE(ACTUAL.Rate, DEF.Rate) AS UseThisRate
    FROM 
      (SELECT 0) DEF (Rate) -- This is your default rate
    LEFT JOIN (
      select rate 
      from d_payment_index
      --WHERE 1=2   -- Uncomment this line to simulate a missing value
    
      --...HERE IF YOUR ACTUAL WHERE CLAUSE. Removed for testing purposes...
      --where fy = 2007
      -- and payment_year = 2008
      --  and program_id = 18
    ) ACTUAL (Rate) ON 1=1
    

    Results

    Valid Rate Exists

    Rate        Rate        UseThisRate
    ----------- ----------- -----------
    0           1           1
    

    Default Rate Used

    Rate        Rate        UseThisRate
    ----------- ----------- -----------
    0           NULL        0
    

    Test DDL

    CREATE TABLE d_payment_index (rate int NOT NULL)
    INSERT INTO d_payment_index VALUES (1)
    
    0 讨论(0)
  • 2020-12-03 07:05

    If your base query is expected to return only one row, then you could use this trick:

    select NVL( MIN(rate), 0 ) AS rate 
    from d_payment_index
    where fy = 2007
      and payment_year = 2008
      and program_id = 18
    

    (Oracle code, not sure if NVL is the right function for SQL Server.)

    0 讨论(0)
提交回复
热议问题