2008-11-12 70 views
21

如果表中没有行,我需要知道如何返回默认行。什么是最好的方法来做到这一点?我只是从这个特定的表中返回一列来获得它的价值。如何为不返回行的查询设置默认行?

编辑:这将是SQL Server。

+0

什么数据库服务器是您使用时,SQL Server,Oracle,MySQL等? – duckworth 2008-11-12 22:47:35

+3

如果您使用SQL Server,为什么接受只适用于Oracle的答案? – 2016-03-25 14:52:23

回答

21

在Oracle:

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

或者:

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

你想返回一整行吗?默认行是否需要具有默认值或者它是否为空行?您是否希望默认行具有与所讨论的表相同的列结构?

根据您的要求,你可能会做这样的事情:

1)运行查询,并放在一个临时表结果(或表变量) 2)检查是否临时表有结果 3)如果没有,通过执行与此类似(SQL Server中的select语句)返回一个空行:

select '' as columnA, '' as columnB, '' as columnC from #tempTable 

凡columnA,columnB和columnC是实际的列名。

1

我想通了,也应该对其他系统的工作了。这是WW的答案的变体。

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

该解决方案的唯一问题是您正在运行查找两次。另一种方法是将结果存储在一个变量中,如果第一个查询的行数为零,则只返回默认值。 – duckworth 2008-11-12 23:27:07

+0

只有其他问题是我在代码中运行这个,所以一个语句是最好的。但是,我同意你的看法。 – 2008-11-12 23:29:37

9

这将是运行两次消除选择查询,并获得更好的性能:使用左

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' 
2

一个表扫描方法从默认加入到实际值:

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] 

给出输出:

k   Value 
----------- ------------ 
0   DefaultValue 

k   Value 
----------- ------------ 
1   1-1 
1   1-2 
1   1-3 

k   Value 
----------- ------------ 
2   2-1 
2   2-2 
12

如果你的基本查询预计只返回一行,那么你可以使用这一招:如果NVL是SQL Server的正确功能

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

(甲骨文代码,不知道。)

6

如何:

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 

结果

有效利率时使用

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

违约率

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

测试DDL

CREATE TABLE d_payment_index (rate int NOT NULL) 
INSERT INTO d_payment_index VALUES (1) 
0

插入您的默认值到一个表变量,然后与你的实际表匹配更新此tableVar的单行。如果找到一行,tableVar将被更新;如果不是,则保留默认值。返回表变量。

---=== The table & its data 
    CREATE TABLE dbo.Rates (
     PkId int, 
     name varchar(10), 
     rate decimal(10,2) 
    ) 
    INSERT INTO dbo.Rates(PkId, name, rate) VALUES (1, 'Schedule 1', 0.1) 
    INSERT INTO dbo.Rates(PkId, name, rate) VALUES (2, 'Schedule 2', 0.2) 

这里的解决方案:

---=== The solution 
CREATE PROCEDURE dbo.GetRate 
    @PkId int 
AS 
BEGIN 
    DECLARE @tempTable TABLE (
    PkId int, 
    name varchar(10), 
    rate decimal(10,2) 
) 

--- [1] Insert default values into @tempTable. PkId=0 is dummy value 
INSERT INTO @tempTable(PkId, name, rate) VALUES (0, 'DEFAULT', 0.00) 

--- [2] Update the single row in @tempTable with the actual value. 
---  This only happens if a match is found 
UPDATE @tempTable 
    SET t.PkId=x.PkId, t.name=x.name, t.rate = x.rate 
    FROM @tempTable t INNER JOIN dbo.Rates x 
    ON t.PkId = 0 
    WHERE x.PkId = @PkId 

SELECT * FROM @tempTable 
END 

测试代码:

EXEC dbo.GetRate @PkId=1  --- returns values for PkId=1 
EXEC dbo.GetRate @PkId=12314 --- returns default values