2008-11-12 45 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