Devuelve un valor si no se encuentran filas en Microsoft tSQL

95

Usando una versión de Microsoft de SQL, aquí está mi consulta simple. Si consulto un registro que no existe, no obtendré nada devuelto. Preferiría que se devuelva falso (0) en ese escenario. Buscando el método más simple para contabilizar ningún 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
Mate
fuente

Respuestas:

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
fuente
La siguiente consulta devuelve un valor único en la condición else, pero lo ideal es que devuelva varios valores. seleccione el caso cuando el recuento (QTIB_REQ _) <1 y luego 0; de lo contrario, QTIB_REQ_ terminará en qb_requisitions_all donde QTIB_REQ_ IN ($ Req_disabled_WA) y CLIENT___BENCH___NON_BILLABLE NOT IN ('No facturable', 'No facturable', 'No facturable', 'Banco - SC Cleared Strategic Hires ',' Bench / US project ') y DATEDIFF (CURDATE (), TARGET_FILL_DATE) <60 y DATEDIFF (CURDATE (), TARGET_FILL_DATE)> 0
Praneet Bahadur
122

Esto es similar al de Adam Robinson, pero usa ISNULL en lugar 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)

Si la consulta interna tiene una fila coincidente, se devuelve 1. La consulta externa (con ISNULL) luego devuelve este valor de 1. Si la consulta interna no tiene una fila coincidente, entonces no devuelve nada. La consulta externa trata esto como un NULL, por lo que ISNULL termina devolviendo 0.

Moe Sisko
fuente
2
¡Gracias por agregar este! Es exactamente lo que necesito, ya que podría SELECT ISNULL ((SELECT Id ... en lugar de 1 para obtener los datos que estaba buscando!
Jesse Smith
3
Muy tarde, lo sé, pero puedes reemplazar ISNULL con COALESCE para lograr el mismo resultado.
BlueChippy
2
Me acostumbré a usar COALESCE en lugar de ISNULL porque, desde la memoria (los hábitos son difíciles), ISNULL no está disponible en SQL Lite o como se llame que se ejecuta en dispositivos Windows Mobile más antiguos. COALESCE funciona en SQL Lite, Express y completo.
Anuncios
1
Funciona mejor, si desea obtener el valor de la variable, en lugar de 0 o 1. La consulta de Adam requiere agrupación o algo así.
Drac
@MoeSisko Me gusta cómo devuelve el 0 si es nulo, pero en lugar de devolver un 1, ¿cómo puedo hacer que devuelva el valor de la tabla?
Michael
21

Esto podría ser un caballo muerto, otra forma de devolver 1 fila cuando no existen filas es UNIONAR otra consulta y mostrar resultados cuando no existen en la tabla.

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
) 
un agente
fuente
2
Usé un método similar al intentar obtener totales de una consulta. Simplemente hice una unión con una consulta que devolvió 0 ( SELECT 0), luego hice una SUMunión. Sencillo y fácil de seguir.
cjbarth
2
Si devuelve 2 filas, ¿se garantiza que las filas se devolverán en el orden esperado?
Zarzaparrilla
Y es pesado en el plan de ejecución
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
fuente
Usé esta solución porque tiene más sentido para mí (no soy tradicionalmente un usuario de SQL). Sin embargo, estoy usando SQL Server, descubrí que agregar el nombre de la columna a esto redondeó esta solución muy bien. es decir, después de que usted select 1y select 2yo agregamosas <colName>
Harvey
8

Leí todas las respuestas aquí y me tomó un tiempo averiguar qué estaba pasando. Lo siguiente se basa en la respuesta de Moe Sisko y algunas investigaciones relacionadas

Si su consulta SQL no devuelve ningún dato, no hay un campo con un valor nulo, por lo que ni ISNULL ni COALESCE funcionarán como usted desea. Al usar una subconsulta, la consulta de nivel superior obtiene un campo con un valor nulo, y tanto ISNULL como COALESCE funcionarán como usted quiere / espera que lo hagan.

Mi consulta

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

Mi consulta con comentarios

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
fuente
5

Solo tienes que reemplazar el DONDE 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

Esta solución también le permite devolver valores predeterminados para cada columna, por ejemplo:

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 ...
Zarzaparrilla
fuente
4

Ningún registro coincidente significa que no se devolvió ningún registro. No hay lugar para el "valor" de 0 si no se encuentran registros. Podría crear una consulta UNION loca para hacer lo que quiera, pero mucho, mucho, mucho mejor simplemente para verificar la cantidad de registros en el conjunto de resultados.

Larry Lustig
fuente
Actualmente, eso es lo que hago. Compruebe que el recuento de registros está vacío o no. Pensé que podrían haber sido una forma de atajar mi cheque.
Matt
Algunas aplicaciones no le permiten verificar "simplemente"
Nadia Solovyeva
3

Esta podría ser una forma.

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
fuente
Me gusta este enfoque. Siento que es un poco más limpio al expresar los datos predeterminados, especialmente si termina con numerosas columnas de datos / valores predeterminados.
Mark At Ramp51
Lol, esta es la mejor y más limpia solución
Kyle Bridenstine
1

¿Y CON LAZOS?

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

La respuesta de @hai-phan LEFT JOINes la clave, pero puede ser un poco difícil de seguir. Tuve una consulta complicada que también puede no devolver nada. Simplemente simplifiqué su respuesta a mi necesidad. Es fácil de aplicar a consultas con muchas columnas.

;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

Actualización: esta respuesta en SqlServerCentral es la mejor. Utiliza esta característica de MAX: "MAX devuelve NULL cuando no hay fila para seleccionar".

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