Verwenden Sie 'Standardwert' in der Tabelle, wenn NULL

7

Ich erstelle eine Konfigurationstabelle und möchte, dass eine Zeile der Standardwert ist. Zum Beispiel habe ich eine listTabelle aller meiner Datenbanken und eine aufgerufene Tabelle, msgdie alle meine Rückgabewerte enthält. In der msgTabelle habe ich eine Zeile mit dem Namen 'alldbs' und möchte, dass dieser Wert zurückgegeben wird, wenn für die verknüpfte Datenbank keine weitere Zeile vorhanden ist.

Die Ausgabe sollte also sein:

--LIST TABLE
dbname                                             createdate
-------------------------------------------------- -----------------------
master                                             2015-06-23 10:05:14.363
model                                              2015-06-23 10:05:14.363
msdb                                               2015-06-23 10:05:14.363
tempdb                                             2015-06-23 10:05:14.363
dummy                                              2015-06-23 10:05:14.363

--MSG Table
dbname                                             msgval
-------------------------------------------------- --------------------
alldbs                                             Message 1
dummy                                              Message 2


--DESIRED OUTPUT
dbname                                             msgval
-------------------------------------------------- --------------------
dummy                                              Message 2
master                                             Message 1
model                                              Message 1
msdb                                               Message 1
tempdb                                             Message 1

Jetzt kann ich das Ergebnis erhalten, aber die Abfrage ist klobig und es scheint, dass es einen besseren Weg geben sollte:

select
    a.dbname
    ,b.msgval
from
    list a
    join msg b on a.dbname = b.dbname
union all
select
    a.dbname
    ,b.msgval
from
    list a
    ,msg b
where
    a.dbname not in (select dbname from msg)
    and b.dbname = 'alldbs'

Gibt es eine effizientere Möglichkeit, diese Abfrage zu schreiben?

SQLFiddle Link mit SQL 2014.

Mike Fal
quelle

Antworten:

8

Verwenden eines anderen left join:

select
    a.dbname
    , coalesce(b.msgval, d.msgval) as msgval
from
    list a
    left join msg b on a.dbname = b.dbname
    left join msg d on  b.dbname is null
                    and d.dbname = 'alldbs' ;

oder ein crossJoin (dies erfordert, dass eine 'alldbs'Zeile vorhanden ist, andernfalls werden 0 Ergebnisse zurückgegeben.):

select
    a.dbname
    , coalesce(b.msgval, d.msgval) as msgval
from
    msg d 
    cross join list a 
    left join msg b on a.dbname = b.dbname
where d.dbname = 'alldbs' ;

SQlfiddle

Bei beiden Abfragen wird davon ausgegangen, dass nur eine Zeile mit vorhanden ist dbname = 'alldbs'. Wenn nicht, verwenden Sie die applyvon AndriyM bereitgestellte Version.

ypercubeᵀᴹ
quelle
7

Ein anderer Weg (nicht so hübsch für mich, nachdem ich den Vorschlag von @ ypercube gesehen habe, aber immer noch ...):

SELECT
  l.dbname,
  x.msgval
FROM
  dbo.list AS l
  CROSS APPLY
    (
      SELECT TOP (1)
        m.msgval
      FROM
        dbo.msg AS m
      WHERE
        m.dbname IN (l.dbname, 'alldbs')
      ORDER BY
        CASE m.dbname WHEN 'alldbs' THEN 2 ELSE 1 END ASC
    ) AS x
;
Andriy M.
quelle
Während ich @ ypercube's als Antwort akzeptiert habe, hat diese Abfrage die niedrigsten logischen Lesevorgänge.
Mike Fal
5

Verwenden einer Unterauswahl, um die fehlende Nachricht abzurufen:

select a.dbname
    ,  coalesce(b.msgval, (select msgval 
                           from msg c 
                           where dbname = 'alldbs')) as msgval 
from list a
left join msg b 
    on a.dbname = b.dbname
Lennart
quelle