est-il possible de sélectionner un peu EXISTS directement?

186

Je me demandais s'il était possible de faire quelque chose comme ça (qui ne fonctionne pas):

select cast( (exists(select * from theTable where theColumn like 'theValue%') as bit)

On dirait que cela devrait être faisable, mais beaucoup de choses qui devraient fonctionner en SQL ne le font pas;) J'ai vu des solutions de contournement pour cela (SELECT 1 où ... existe ...) mais il semble que je devrais être capable de simplement cast le résultat de la fonction existe un peu et en finir avec elle.

jcollum
la source

Réponses:

267

Non, vous devrez utiliser une solution de contournement.

Si vous devez renvoyer un bit conditionnel 0/1, une autre façon est de:

SELECT CAST(
   CASE WHEN EXISTS(SELECT * FROM theTable where theColumn like 'theValue%') THEN 1 
   ELSE 0 
   END 
AS BIT)

Ou sans le casting:

SELECT
   CASE
       WHEN EXISTS( SELECT 1 FROM theTable WHERE theColumn LIKE 'theValue%' )
            THEN 1 
       ELSE 0 
   END
Alex K.
la source
16
Vous n'avez pas besoin de la conversion si vous stockez le résultat dans un type de données Bit car la conversion est déjà implicite.
MikeTeeVee
3
Je viens de tester cette technique, fonctionne très bien. Le CAST to BIT n'est pas nécessaire pour récupérer les résultats de la requête, testée avec SQL Server 2008 R2.
Tore Aurstad
Dans mon cas, le casting DOIT être retiré
Sérgio S.Filho
51
SELECT CAST(COUNT(*) AS bit) FROM MyTable WHERE theColumn like 'theValue%'

Lorsque vous jetez à mordre

  • 0 -> 0
  • tout le reste -> 1
  • Et NULL -> NULL bien sûr, mais vous ne pouvez pas obtenir NULL avec COUNT (*) sans GROUP BY

bit correspond directement à boolean types de données .net, même si ce n'est pas vraiment le cas ...

Cela semble similaire mais ne donne aucune ligne (pas zéro) si aucune correspondance, donc ce n'est pas la même chose

SELECT TOP 1 CAST(NumberKeyCOlumn AS bit) FROM MyTable WHERE theColumn like 'theValue%'
gbn
la source
4
Mais cela n'utilise pas du tout EXISTS. Je ne demandais pas comment contourner le problème, je peux trouver des solutions de contournement, je demandais s'il y avait une astuce à utiliser existe comme un peu dont je n'étais pas au courant.
jcollum
6
Ce n'est pas une solution de contournement, c'est une manière correcte de définir. EXISTS est cette solution de contournement ... Et très propre, non?
gbn
1
@jcollum: oui, ou quelque chose comme ça. EXISTS est presque toujours IF EXISTS ou WHERE EXISTS et n'est pas utilisé pour la sortie comme vous essayez de le faire
gbn
14
EXISTS est plus efficace que COUNT lors de la vérification de l'existence d'un enregistrement - voir sqlblog.com/blogs/andrew_kelly/archive/2007/12/15/…
Tahir Hassan
9
Contrairement à EXISTS, COUNTcontinuera à rechercher dans les données les lignes correspondantes même après avoir trouvé la première, car il doit obtenir le nombre.
IsmailS
11

Je suis un peu en retard sur l'adoption de cela; vient de trébucher sur le message. Cependant, voici une solution qui est plus efficace et soignée que la réponse choisie, mais qui devrait donner la même fonctionnalité:

declare @t table (name nvarchar(16))
declare @b bit

insert @t select N'Simon Byorg' union select N'Roe Bott'


select @b = isnull((select top 1 1 from @t where name = N'Simon Byorg'),0)
select @b whenTrue

select @b = isnull((select top 1 1 from @t where name = N'Anne Droid'),0)
select @b whenFalse
JohnLBevan
la source
7

Vous pouvez utiliser IIFetCAST

SELECT CAST(IIF(EXISTS(SELECT * FROM theTable 
                       where theColumn like 'theValue%'), 1, 0) AS BIT)
Jaider
la source
1
J'aime cela, mais cela ne fonctionne que dans SQL Server 2012 et plus. On dirait que IIF a été ajouté en 2012
ja928
5

Vous pouvez également effectuer les opérations suivantes:

SELECT DISTINCT 1
  FROM theTable
 WHERE theColumn LIKE 'theValue%'

S'il n'y a pas de valeurs commençant par 'theValue', cela retournera null (pas d'enregistrements) au lieu d'un bit 0

Nelson
la source
2

Non, ce n'est pas possible. Le type de données bit n'est pas un type de données booléen. C'est un type de données entier qui peut être 0,1 ou NULL.

Martin Smith
la source
3
@bzlm Oui, c'est possible dans SQLServer depuis plus de 10 ans. SQL Server 7.0 l'a introduit msdn.microsoft.com/en-us/library/aa237157%28SQL.80%29.aspx
Martin Smith
4
@bzlm - Il semble que vous vous agrippez à des pailles et que vous ne savez vraiment rien des types de données SQL Server pour moi. La définition de bit dans SQL Server est «Un type de données entier qui peut prendre une valeur de 1, 0 ou NULL». msdn.microsoft.com/en-us/library/ms177603.aspx . Cela s'applique aux colonnes et aux variables Transact SQL. Nulle part une variable bit ne peut être utilisée comme booléenne en SQL avec IF(@TRUE)par exemple, ni vice-versa une expression booléenne ne peut être forcée en un bit. (Avec par exemple SET @BitVariable = (1=1))
Martin Smith
1
Je vois où vous allez, mais le casting en bit n'était pas tant le problème que de pouvoir sélectionner EXISTS directement.
jcollum
1

Une autre solution consiste à utiliser ISNULLen tandem avec SELECT TOP 1 1:

SELECT ISNULL((SELECT TOP 1 1 FROM theTable where theColumn like 'theValue%'), 0)
Anar Khalilov
la source
-1

Je crois qu'exister ne peut être utilisé que dans une clause where, vous devrez donc faire une solution de contournement (ou une sous-requête avec existe comme clause where). Je ne sais pas si cela compte comme une solution de contournement.

Et ça:

create table table1 (col1   int null)
go
select 'no items',CONVERT(bit, (select COUNT(*) from table1) )   -- returns 'no items', 0
go
insert into table1 (col1) values (1)
go
select '1 item',CONVERT(bit, (select COUNT(*) from table1) )     --returns '1 item', 1
go
insert into table1 (col1) values (2)
go
select '2 items',CONVERT(bit, (select COUNT(*) from table1) )    --returns '2 items', 1
go
insert into table1 (col1) values (3)
go
drop table table1
go
ScottK
la source
Qu'en est-il des cas dans une sélection?
lowerkey
-1
SELECT IIF(EXISTS(SELECT * FROM theTable WHERE theColumn LIKE 'theValue%'), 1, 0)
MEC
la source