web-dev-qa-db-fra.com

Renvoie une valeur si aucune ligne n'est trouvée SQL

Voici ma requête simple. Si j'interroge un enregistrement qui n'existe pas, rien ne me sera retourné. Je préférerais que false (0) soit renvoyé dans ce scénario. Vous recherchez la méthode simpliste pour ne prendre en compte aucun enregistrement.

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
71
Matt
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)
53
Adam Robinson

Ceci est similaire à Adam Robinson, mais utilise ISNULL au lieu 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 requête interne a une ligne correspondante, 1 est renvoyé. La requête externe (avec ISNULL) renvoie alors la valeur 1. Si la requête interne ne comporte aucune ligne correspondante, elle ne renvoie rien. La requête externe traite cela comme une valeur NULL et ISNULL renvoie donc 0.

94
Moe Sisko

Cela peut être un cheval mort, un autre moyen de renvoyer une ligne lorsqu'il n'en existe aucune consiste à UNION une autre requête et d'afficher les résultats lorsqu'il n'existe pas dans la table. 

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
) 
12
anAgent

Quelque chose comme:

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
6
Ellis

J'ai lu toutes les réponses ici et il a fallu un certain temps pour comprendre ce qui se passait. Ce qui suit est basé sur la réponse de Moe Sisko et quelques recherches connexes

Si votre requête SQL ne renvoie aucune donnée, il n'existe pas de champ avec une valeur null. Ni ISNULL ni COALESCE ne fonctionneront comme vous le souhaitez. En utilisant une sous-requête, la requête de niveau supérieur obtient un champ avec une valeur null et ISNULL et COALESCE fonctionneront comme vous le souhaitez.

Ma requête

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

Ma requête avec commentaires

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
James Jenkins

Il suffit de remplacer le WHERE par 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

Cette solution vous permet également de renvoyer des valeurs par défaut pour chaque colonne, par exemple:

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
Hai Phan

Aucun enregistrement ne correspond à aucun enregistrement renvoyé. Il n'y a pas de place pour que la "valeur" de 0 aille si aucun enregistrement n'est trouvé. Vous pouvez créer une requête UNION délirante pour faire ce que vous voulez mais beaucoup, beaucoup mieux simplement vérifier le nombre d'enregistrements dans l'ensemble de résultats.

4
Larry Lustig

Et avec les liens?

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
Fandango68

Cela pourrait être à sens unique.

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

La réponse de @ hai-phan utilisant LEFT JOIN est la clé, mais cela peut être un peu difficile à suivre. J'ai eu une requête très compliquée qui peut aussi ne rien renvoyer. Je viens de simplifier sa réponse comme suit pour mon besoin. Il est facile d'appliquer une requête avec plusieurs colonnes.

;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
0
kakugiki