Renvoie une valeur si aucune ligne n'est trouvée dans Microsoft tSQL

95

En utilisant une version Microsoft de SQL, voici ma requête simple. Si j'interroge un enregistrement qui n'existe pas, je ne recevrai rien. Je préférerais que false (0) soit renvoyé dans ce scénario. Vous recherchez la méthode la plus simple pour ne tenir compte d'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
Mat
la source

Réponses:

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
la source
La requête ci-dessous renvoie une valeur unique dans la condition else, mais idéalement, elle doit renvoyer plusieurs valeurs. sélectionner le cas où count (QTIB_REQ _) <1 puis 0 else QTIB_REQ_ end from qb_requisitions_all où QTIB_REQ_ IN ($ Req_disabled_WA) et CLIENT___BENCH___NON_BILLABLE NOT IN ('Non facturable', 'Non facturable', 'Non facturable', 'Bancaire SC Cleared Strategic Hires ',' Bench / US project ') et DATEDIFF (CURDATE (), TARGET_FILL_DATE) <60 et DATEDIFF (CURDATE (), TARGET_FILL_DATE)> 0
Praneet Bahadur
123

Ceci est similaire à celui d'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 cette valeur de 1. Si la requête interne n'a pas de ligne correspondante, alors elle ne renvoie rien. La requête externe traite cela comme un NULL, et donc ISNULL finit par renvoyer 0.

Moe Sisko
la source
2
Merci d'avoir ajouté celui-ci! C'est exactement ce dont j'ai besoin, car je pourrais simplement SELECT ISNULL ((SELECT Id ... au lieu de 1 pour obtenir les données que je cherchais!
Jesse Smith
3
Très tard, je sais, mais vous pouvez remplacer ISNULL par COALESCE pour obtenir le même résultat.
BlueChippy
2
J'ai pris l'habitude d'utiliser COALESCE plutôt que ISNULL parce que, de mémoire (les habitudes sont mortelles), ISNULL n'est pas disponible dans SQL Lite ou quoi que ce soit qui fonctionne sur les anciens appareils Windows Mobile. COALESCE fonctionne à la fois sur SQL léger, Express et complet.
Annonces du
1
Cela fonctionne mieux, si vous voulez obtenir une valeur de variable, au lieu de 0 ou 1. La requête d'Adam nécessite un regroupement ou quelque chose comme ça.
Drac
@MoeSisko J'aime comment il renvoie le 0 s'il est nul, mais au lieu de renvoyer un 1, comment puis-je lui faire renvoyer la valeur de la table?
Michael
21

Cela peut être un cheval mort, une autre façon de renvoyer 1 ligne quand aucune ligne n'existe est d'UNION une autre requête et d'afficher les résultats lorsqu'ils n'existent 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
) 
un agent
la source
2
J'ai utilisé une méthode similaire en essayant d'obtenir des totaux à partir d'une requête. J'ai simplement fait une union avec une requête qui retournait 0 ( SELECT 0), puis j'ai fait une SUMsur l'union. Simple et facile à suivre.
cjbarth
2
S'il renvoie 2 lignes, est-il garanti que les lignes seront renvoyées dans l'ordre attendu?
Salsepareille le
Et c'est lourd sur le plan d'exécution
Fandango68
12

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
Ellis
la source
J'ai utilisé cette solution car elle a plus de sens pour moi (je ne suis pas traditionnellement un utilisateur SQL), cependant, j'utilise SQL Server, j'ai trouvé que l'ajout du nom de col à cette solution arrondissait bien cette solution. c'est-à-dire après votre select 1et select 2j'ai ajoutéas <colName>
Harvey
8

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 certaines recherches connexes

Si votre requête SQL ne renvoie aucune donnée, il n'y a pas de champ avec une valeur nulle, donc 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 nulle, et ISNULL et COALESCE fonctionneront comme vous le souhaitez / attendez d'eux.

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

Il vous suffit de remplacer le WHERE par un GAUCHE 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 ...
Salsepareille
la source
4

Aucun enregistrement correspondant signifie qu'aucun enregistrement n'est retourné. Il n'y a pas de place pour la "valeur" de 0 si aucun enregistrement n'est trouvé. Vous pouvez créer une requête UNION folle pour faire ce que vous voulez mais beaucoup, beaucoup, beaucoup mieux simplement pour vérifier le nombre d'enregistrements dans le jeu de résultats.

Larry Lustig
la source
Actuellement, c'est ce que je fais. Vérifiez que le nombre d'enregistrements est vide ou non. Je pensais que c'était peut-être un moyen de raccourcir mon chèque.
Matt
Certaines applications ne vous permettent pas de vérifier "simplement"
Nadia Solovyeva
3

Cela pourrait être un moyen.

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
la source
J'aime cette approche. Je pense que c'est un peu plus propre lors de l'expression des données par défaut, surtout si vous vous retrouvez avec de nombreuses colonnes de données / valeurs par défaut.
Mark At Ramp51
Lol c'est la solution la meilleure et la plus propre
Kyle Bridenstine le
1

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

La réponse de @ hai-phan en utilisant LEFT JOINest la clé, mais cela peut être un peu difficile à suivre. J'ai eu une requête compliquée qui peut également ne rien renvoyer. J'ai simplement simplifié sa réponse à mon besoin. Il est facile d'appliquer une requête avec de nombreuses 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

Mise à jour: Cette réponse sur SqlServerCentral est la meilleure. Il utilise cette fonctionnalité de MAX - "MAX renvoie NULL lorsqu'il n'y a pas de ligne à sélectionner."

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