Restituisce un valore se non vengono trovate righe in Microsoft tSQL


95

Utilizzando una versione Microsoft di SQL, ecco la mia semplice domanda. Se interrogo un record che non esiste, non verrà restituito nulla. Preferirei che false (0) fosse restituito in quello scenario. Alla ricerca del metodo più semplice per tenere conto di nessun record.

SELECT  CASE
            WHEN S.Id IS NOT NULL AND S.Status = 1 AND (S.WebUserId = @WebUserId OR S.AllowUploads = 1) THEN 1
            ELSE 0
        END AS [Value]

        FROM Sites S

        WHERE S.Id = @SiteId

Risposte:


64
SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS [Value]

FROM Sites S

WHERE S.Id = @SiteId and S.Status = 1 AND 
      (S.WebUserId = @WebUserId OR S.AllowUploads = 1)

La query sottostante restituisce un valore singolo in condizioni else, ma idealmente dovrebbe restituire più valori. seleziona il caso in cui count (QTIB_REQ _) <1 then 0 else QTIB_REQ_ end from qb_requisitions_all dove QTIB_REQ_ IN ($ Req_disabled_WA) e CLIENT___BENCH___NON_BILLABLE NOT IN ('Non Billable', 'Non-Billable', 'NonBillable', 'Bench' SC Cleared Strategic Hires ',' Bench / US project ') e DATEDIFF (CURDATE (), TARGET_FILL_DATE) <60 e DATEDIFF (CURDATE (), TARGET_FILL_DATE)> 0
Praneet Bahadur

122

È simile a quello di Adam Robinson, ma utilizza ISNULL invece di COUNT.

SELECT ISNULL(
(SELECT 1 FROM Sites S
WHERE S.Id = @SiteId and S.Status = 1 AND 
      (S.WebUserId = @WebUserId OR S.AllowUploads = 1)), 0)

Se la query interna ha una riga corrispondente, viene restituito 1. La query esterna (con ISNULL) restituisce quindi questo valore di 1. Se la query interna non ha una riga corrispondente, non restituisce nulla. La query esterna lo tratta come un NULL, quindi ISNULL finisce per restituire 0.


2
Grazie per aver aggiunto questo! È esattamente ciò di cui ho bisogno, dato che potrei semplicemente SELEZIONARE ISNULL ((SELECT Id ... invece di 1 per ottenere i dati che stavo cercando!
Jesse Smith

3
Molto tardi, lo so, ma puoi sostituire ISNULL con COALESCE per ottenere lo stesso risultato.
BlueChippy

2
Ho preso l'abitudine di usare COALESCE piuttosto che ISNULL perché, dalla memoria (le abitudini sono dure a morire), ISNULL non è disponibile in SQL Lite o come viene chiamato che gira su vecchi dispositivi Windows Mobile. COALESCE funziona su entrambi, lite, Express e SQL completo.
Annunci

1
Funziona meglio, se vuoi ottenere un valore variabile, invece di 0 o 1. La query di Adam richiede il raggruppamento o qualcosa del genere.
Drac

@MoeSisko mi piace come restituisce lo 0 se è nullo, ma invece di restituire un 1, come posso fare in modo che restituisca il valore dalla tabella?
Michael il

21

Questo potrebbe essere un cavallo morto, un altro modo per restituire 1 riga quando non esistono righe è UNION un'altra query e visualizzare i risultati quando non esistono nella tabella.

SELECT S.Status, COUNT(s.id) AS StatusCount
FROM Sites S
WHERE S.Id = @SiteId
GROUP BY s.Status
UNION ALL --UNION BACK ON TABLE WITH NOT EXISTS
SELECT 'N/A' AS Status, 0 AS StatusCount
WHERE NOT EXISTS (SELECT 1
   FROM Sites S
   WHERE S.Id = @SiteId
) 

2
Ho usato un metodo simile quando cercavo di ottenere i totali da una query. Ho semplicemente fatto un'unione con una query che ha restituito 0 ( SELECT 0), quindi ho fatto SUMun'unione. Semplice e facile da seguire.
cjbarth

2
Se restituisce 2 righe, è garantito che le righe verranno restituite nell'ordine previsto?
Sarsaparilla

Ed è pesante sul piano di esecuzione
Fandango68

12

Qualcosa di simile a:

if exists (select top 1 * from Sites S where S.Id IS NOT NULL AND S.Status = 1 AND (S.WebUserId = @WebUserId OR S.AllowUploads = 1))
    select 1
else
    select 0

Ho usato questa soluzione perché ha più senso per me (non sono tradizionalmente un utente SQL), Tuttavia, sto usando SQL Server, ho scoperto che l'aggiunta del nome col a questa soluzione ha arrotondato bene questa soluzione. cioè dopo il tuo select 1e select 2ho aggiuntoas <colName>
Harvey

8

Ho letto tutte le risposte qui e ci è voluto un po 'per capire cosa stava succedendo. Quanto segue si basa sulla risposta di Moe Sisko e su alcune ricerche correlate

Se la tua query SQL non restituisce alcun dato, non è presente un campo con un valore nullo, quindi né ISNULL né COALESCE funzioneranno come desideri. Utilizzando una sottoquery, la query di primo livello ottiene un campo con un valore nullo e sia ISNULL che COALESCE funzioneranno come desideri / ti aspetti che facciano.

La mia domanda

select isnull(
 (select ASSIGNMENTM1.NAME
 from dbo.ASSIGNMENTM1
 where ASSIGNMENTM1.NAME = ?)
, 'Nothing Found') as 'ASSIGNMENTM1.NAME'

La mia domanda con i commenti

select isnull(
--sub query either returns a value or returns nothing (no value)
 (select ASSIGNMENTM1.NAME
 from dbo.ASSIGNMENTM1
 where ASSIGNMENTM1.NAME = ?)
 --If there is a value it is displayed 
 --If no value, it is perceived as a field with a null value, 
 --so the isnull function can give the desired results
, 'Nothing Found') as 'ASSIGNMENTM1.NAME'

5

Devi solo sostituire il WHERE con un LEFT JOIN:

SELECT  CASE
        WHEN S.Id IS NOT NULL AND S.Status = 1 AND ...) THEN 1
        ELSE 0
    END AS [Value]

    FROM (SELECT @SiteId AS Id) R
    LEFT JOIN Sites S ON S.Id = R.Id

Questa soluzione consente di restituire valori predefiniti per ogni colonna anche, ad esempio:

SELECT
    CASE WHEN S.Id IS NULL THEN 0 ELSE S.Col1 END AS Col1,
    S.Col2,
    ISNULL(S.Col3, 0) AS Col3
FROM
    (SELECT @Id AS Id) R
    LEFT JOIN Sites S ON S.Id = R.Id AND S.Status = 1 AND ...

4

Nessun record corrispondente significa nessun record restituito. Non c'è posto per il "valore" di 0 se non vengono trovati record. Potresti creare una folle query UNION per fare quello che vuoi ma molto, molto, molto meglio semplicemente per controllare il numero di record nel set di risultati.


Attualmente è quello che faccio. Controlla se il conteggio dei record è vuoto o meno. Ho pensato che potessero essere un modo per abbreviare il mio assegno.
Matt

Alcune app non ti consentono di controllare "semplicemente"
Nadia Solovyeva

3

Questo potrebbe essere un modo.

SELECT TOP 1 [Column Name] FROM (SELECT [Column Name] FROM [table]
    WHERE [conditions]
    UNION ALL
    SELECT 0 )A ORDER BY [Column Name] DESC

Mi piace questo approccio. Penso che sia un po 'più pulito quando si esprimono i dati predefiniti, soprattutto se si finisce con numerose colonne di dati / valori predefiniti.
Mark At Ramp51

Lol questa è la soluzione migliore e più pulita
Kyle Bridenstine

1

Che ne dici di WITH TIES?

SELECT TOP 1 WITH TIES tbl1.* FROM 
        (SELECT CASE WHEN S.Id IS NOT NULL AND S.Status = 1 
                      AND (S.WebUserId = @WebUserId OR 
                           S.AllowUploads = 1)
                     THEN 1 
                     ELSE 0 AS [Value]
         FROM Sites S
         WHERE S.Id = @SiteId) as tbl1
ORDER BY tbl1.[Value]

1
DECLARE @col int; 
select @col = id  FROM site WHERE status = 1; 
select coalesce(@col,0);

0

La risposta di @ hai-phan LEFT JOINè la chiave, ma potrebbe essere un po 'difficile da seguire. Ho avuto una query complicata che potrebbe anche non restituire nulla. Ho solo semplificato la sua risposta al mio bisogno. È facile da applicare a query con molte colonne.

;WITH CTE AS (
  -- SELECT S.Id, ...
  -- FROM Sites S WHERE Id = @SiteId
  -- EXCEPT SOME CONDITION.
  -- Whatever your query is
)
SELECT CTE.* -- If you want something else instead of NULL, use COALESCE.
FROM (SELECT @SiteId AS ID) R
LEFT JOIN CTE ON CTE.Id = R.ID

Aggiornamento: questa risposta su SqlServerCentral è la migliore. Utilizza questa funzione di MAX - "MAX restituisce NULL quando non ci sono righe da selezionare."

SELECT ISNULL(MAX(value), 0) FROM table WHERE Id = @SiteId

0
You should avoid using expensive methods. You dont need any column for TBL2. 

SELECT COUNT(*) FROM(
         SELECT TOP 1     1 AS CNT  FROM  TBL1 
         WHERE ColumnValue ='FooDoo'  ) AS TBL2

or

IF EXISTS (SELECT TOP 1 1 FROM TABLE1 AS T1 
                          WHERE T1.ColumnValue='VooDoo') 
   SELECT 1 
ELSE 
   SELECT 0
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.