Retorna um valor se nenhuma linha for encontrada no Microsoft tSQL

94

Usando uma versão Microsoft do SQL, aqui está minha consulta simples. Se eu consultar um registro que não existe, nada retornarei. Eu prefiro que false (0) seja retornado nesse cenário. Procurando o método mais simples de contabilizar nenhum registro.

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
Matt
fonte

Respostas:

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)
Adam Robinson
fonte
Abaixo, a consulta retorna um valor único em outra condição, mas o ideal é que ela retorne vários valores. selecione o caso quando a contagem (QTIB_REQ _) <1 então 0 else QTIB_REQ_ termina de qb_requisitions_all onde QTIB_REQ_ IN ($ Req_disabled_WA) e CLIENT___BENCH___NON_BILLABLE NOT IN ('Não faturável', 'Não faturável', 'Não faturável', 'Não faturável', 'Bancada' SC Cleared Strategic Hires ',' Bench / US project ') e DATEDIFF (CURDATE (), TARGET_FILL_DATE) <60 e DATEDIFF (CURDATE (), TARGET_FILL_DATE)> 0
Praneet Bahadur
121

É semelhante ao de Adam Robinson, mas usa ISNULL em vez de 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 a consulta interna tiver uma linha correspondente, 1 será retornado. A consulta externa (com ISNULL) retorna este valor de 1. Se a consulta interna não tiver nenhuma linha correspondente, ela não retornará nada. A consulta externa trata isso como um NULL e, portanto, o ISNULL acaba retornando 0.

Moe Sisko
fonte
2
Obrigado por adicionar este! É exatamente o que eu preciso, pois poderia apenas SELECT ISNULL ((SELECT Id ... em vez de 1 para obter os dados que eu estava procurando!
Jesse Smith
3
Muito tarde, eu sei, mas você pode substituir ISNULL por COALESCE para obter o mesmo resultado.
BlueChippy
2
Adquiri o hábito de usar COALESCE em vez de ISNULL porque, de memória (os hábitos são difíceis de morrer), ISNULL não está disponível no SQL Lite ou qualquer outro nome que seja executado em dispositivos Windows Mobile mais antigos. COALESCE funciona em ambos, lite, Express e SQL completo.
Anúncios de
1
Funciona melhor, se você quiser obter o valor da variável, em vez de 0 ou 1. A consulta de Adam requer agrupamento ou algo parecido.
Drac
@MoeSisko Gosto de como ele retorna 0 se for nulo, mas em vez de retornar 1, como posso fazer com que ele retorne o valor da tabela?
Michael
21

Isso pode ser um cavalo morto, outra maneira de retornar 1 linha quando nenhuma linha existir é UNIONAR outra consulta e exibir os resultados quando não existirem na tabela.

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
) 
um agente
fonte
2
Usei um método semelhante ao tentar obter os totais de uma consulta. Eu simplesmente fiz uma união com uma consulta que retornou 0 ( SELECT 0), depois fiz uma SUMna união. Simples e fácil de seguir.
cjbarth
2
Se ele retornar 2 linhas, é garantido que as linhas serão retornadas na ordem esperada?
Salsaparrilha de
E pesa no plano de execução
Fandango68
12

Algo como:

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
Ellis
fonte
Usei esta solução porque faz mais sentido para mim (não sou tradicionalmente um usuário SQL), no entanto, estou usando o SQL Server, descobri que adicionar o nome col a esta solução arredondada. ou seja, depois que você select 1e select 2eu adicionamosas <colName>
Harvey
8

Li todas as respostas aqui e demorou um pouco para descobrir o que estava acontecendo. O seguinte é baseado na resposta de Moe Sisko e em algumas pesquisas relacionadas

Se sua consulta SQL não retornar nenhum dado, não há um campo com valor nulo, portanto nem ISNULL nem COALESCE funcionarão como você deseja. Usando uma subconsulta, a consulta de nível superior obtém um campo com um valor nulo e tanto ISNULL quanto COALESCE funcionarão como você deseja / espera.

Minha consulta

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

Minha consulta com comentários

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'
James Jenkins
fonte
5

Você só precisa substituir WHERE por 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

Esta solução permite que você retorne valores padrão para cada coluna também, por exemplo:

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 ...
Salsaparrilha
fonte
4

Nenhum registro correspondente significa nenhum registro retornado. Não há lugar para o "valor" de 0 ir se nenhum registro for encontrado. Você poderia criar uma consulta UNION maluca para fazer o que quiser, mas muito, muito, muito melhor simplesmente verificar o número de registros no conjunto de resultados.

Larry Lustig
fonte
Atualmente, é isso que eu faço. Verifique se a contagem de registros está vazia ou não. Percebi que podem ter sido uma forma de reduzir meu cheque.
Matt,
Alguns aplicativos não permitem que você verifique "simplesmente"
Nadia Solovyeva de
3

Isso pode ser uma maneira.

SELECT TOP 1 [Column Name] FROM (SELECT [Column Name] FROM [table]
    WHERE [conditions]
    UNION ALL
    SELECT 0 )A ORDER BY [Column Name] DESC
Gopal V
fonte
Eu gosto dessa abordagem. Eu sinto que é um pouco mais claro ao expressar os dados padrão, especialmente se você acabar com várias colunas de dados / valores padrão.
Mark At Ramp51
Lol esta é a solução melhor e mais limpa
Kyle Bridenstine
1

E COM LAÇOS?

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]
Fandango68
fonte
1
DECLARE @col int; 
select @col = id  FROM site WHERE status = 1; 
select coalesce(@col,0);
Preto
fonte
0

A resposta de @hai-phan usando LEFT JOINé a chave, mas pode ser um pouco difícil de entender. Tive uma consulta complicada que também pode não retornar nada. Eu apenas simplifiquei sua resposta à minha necessidade. É fácil aplicar a consulta com muitas colunas.

;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

Atualização: Esta resposta no SqlServerCentral é a melhor. Ele utiliza este recurso de MAX - "MAX retorna NULL quando não há linha para selecionar."

SELECT ISNULL(MAX(value), 0) FROM table WHERE Id = @SiteId
Weihui Guo
fonte
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
Ayhan Sarıtaş
fonte