2008-11-12 26 views
21

Tôi cần biết cách trả về hàng mặc định nếu không có hàng nào tồn tại trong bảng. cách nào tốt nhất để làm việc này? Tôi chỉ trả lại một cột từ bảng cụ thể này để lấy giá trị của nó.Cách đặt hàng mặc định cho truy vấn không trả về hàng nào?

Chỉnh sửa: Đây sẽ là SQL Server.

+0

cơ sở dữ liệu gì bạn đang sử dụng, SQL Server, Oracle, MySQL? – duckworth

+3

Nếu bạn đang sử dụng SQL Server, tại sao chấp nhận câu trả lời chỉ hoạt động trên Oracle? –

Trả lời

21

Trong Oracle:

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

Hoặc cách khác:

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

Bạn có muốn trả lại một hàng đầy đủ không? Hàng mặc định có cần phải có giá trị mặc định hoặc có thể là hàng trống không? Bạn có muốn hàng mặc định có cùng cấu trúc cột như bảng được đề cập không?

Tùy thuộc vào yêu cầu của bạn, bạn có thể làm điều gì đó như thế này:

1) chạy truy vấn và đặt kết quả trong một bảng tạm thời (hoặc biến bảng) 2) kiểm tra xem bảng tạm thời có kết quả 3) nếu không, trả về hàng trống bằng cách thực hiện một câu lệnh chọn tương tự như thế này (trong SQL Server):

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

Trường hợp cột, tên cột và cộtC là tên cột thực tế của bạn.

1

I figured it out, và nó cũng nên làm việc cho các hệ thống khác nữa. Đó là một biến thể của câu trả lời của 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

Vấn đề duy nhất với giải pháp đó là bạn đang chạy tra cứu hai lần. Một giải pháp thay thế sẽ là lưu trữ kết quả của bạn trong một biến và chỉ trả lại giá trị mặc định nếu số đếm hàng của bạn từ truy vấn đầu tiên bằng không. – duckworth

+0

Th chỉ có vấn đề khác là tôi đang chạy điều này trong mã, do đó, một tuyên bố duy nhất là tốt nhất. Nhưng có, tôi đồng ý với bạn. –

+1

Tùy thuộc vào ảnh lớn hơn, bạn có thể thực sự muốn có một OUTER JOIN ở đây. Nếu đây là bên trong một vòng lặp thông qua một recordset có lẽ có những cách tốt hơn. –

9

này sẽ loại bỏ các truy vấn chọn từ chạy hai lần và tốt hơn cho hiệu suất:

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

thats câu trả lời tốt ... –

2

Một bảng quét phương pháp sử dụng một trái tham gia từ mặc định là 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] 

Cung cấp đầu ra:

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

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

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

Nếu truy vấn cơ sở của bạn được kỳ vọng sẽ trở lại chỉ có một hàng, sau đó bạn có thể sử dụng thủ thuật này:

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

(Oracle mã, không chắc chắn nếu NVL là chức năng phù hợp với SQL Server.)

+0

ISNULL là SQL Server tương đương với NVL ... :-) –

+5

Câu hỏi đặt ra là cách trả về giá trị mặc định khi không có hàng nào được trả về. – WarrenT

+0

Truy vấn này vẫn có thể mang lại 0 bản ghi nếu không có bản ghi khớp với mệnh đề 'where'. NVL/ISNULL của bạn sẽ chỉ chuyển đổi giá trị null thành 0 khi một bản ghi tồn tại và giá trị của nó là ** null **. –

6

Làm thế nào về điều này:

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 

Kết quả

Rate trị Tồn tại

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

Mặc định Tỷ lệ sử dụng

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

thử nghiệm DDL

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

Chèn giá trị mặc định của bạn thành một biến bảng, sau đó cập nhật hàng duy nhất của tableVar này với một trận đấu từ bảng thực tế của bạn. Nếu tìm thấy hàng, tableVar sẽ được cập nhật; nếu không, giá trị mặc định vẫn còn. Trả về biến bảng.

---=== 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) 

Dưới đây là giải pháp:

---=== 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 

Kiểm tra mã:

máy chủ
EXEC dbo.GetRate @PkId=1  --- returns values for PkId=1 
EXEC dbo.GetRate @PkId=12314 --- returns default values 
Các vấn đề liên quan