2008-11-12 11 views
21

Necesito saber cómo devolver una fila predeterminada si no hay filas en una tabla. Cuál sería la mejor forma de hacer esto? Solo estoy devolviendo una sola columna de esta tabla en particular para obtener su valor.¿Cómo establecer una fila predeterminada para una consulta que no devuelve filas?

Editar: Esto sería SQL Server.

+0

Qué base de datos está usando, SQL Server, Oracle, MySQL? – duckworth

+3

Si está usando SQL Server, ¿por qué aceptar una respuesta que solo funciona en Oracle? –

Respuesta

21

En Oracle:

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

O, alternativamente:

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

¿Desea devolver una fila completa? ¿La fila predeterminada debe tener valores predeterminados o puede ser una fila vacía? ¿Desea que la fila predeterminada tenga la misma estructura de columnas que la tabla en cuestión?

Dependiendo de sus necesidades, es posible hacer algo como esto:

1) ejecutar la consulta y poner los resultados en una tabla temporal (o variable de tabla) 2) comprobar para ver si la tabla temporal tiene resultados 3) Si no es así, devolver una fila vacía mediante la realización de una instrucción de selección similar a esto (en SQL Server):

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

Dónde columna, ColumnB y ColumnC son los nombres de las columnas reales.

1

lo he descubierto, y también debería funcionar para otros sistemas también. Es una variación de la respuesta de 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

El único problema con esa solución es que está ejecutando la búsqueda dos veces. Una alternativa sería almacenar el resultado en una variable y solo devolver el valor predeterminado si su recuento de filas de la primera consulta fue cero. – duckworth

+0

Th solo otro problema es que estoy ejecutando esto en código, por lo que una declaración única es la mejor. Pero sí, estoy de acuerdo contigo. –

+1

Dependiendo de la imagen más grande, es posible que realmente desee una OUTER JOIN aquí. Si esto está dentro de un bucle a través de un conjunto de registros, probablemente haya formas mejores. –

9

Esto sería eliminar la consulta de selección se ejecute dos veces y ser mejor para el rendimiento: método de exploración

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

esa es una buena respuesta ... –

2

Una tabla usando una combinación izquierda de incumplimientos a los datos reales:

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] 

Da salida:

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

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

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

si se espera que la consulta de base para devolver sólo una fila, entonces se podría utilizar este truco:

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

(código de Oracle, no estoy seguro si es la función NVL derecha para SQL Server.)

+0

ISNULL es el Servidor SQL equivalente a NVL ... :-) –

+5

La pregunta es cómo devolver los valores predeterminados cuando NO se devuelven las filas. – WarrenT

+0

Esta consulta aún puede generar 0 registros si ningún registro coincide con la cláusula 'where'. Su NVL/ISNULL solo convertirá los valores nulos en 0 cuando exista un registro y su valor sea ** nulo **. –

6

¿Qué tal esto:

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 

Resultados

tipo válido Exists Tasa

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

predeterminada Se utiliza

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

prueba DDL

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

Inserte sus valores por defecto en una variable de tabla, a continuación, actualizar una sola fila de este tableVar con un partido de su mesa real. Si se encuentra una fila, se actualizará tableVar; si no, el valor predeterminado permanece. Devuelve la variable de la tabla.

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

Aquí está la solución:

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

prueba el código:

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