czy można trochę wybrać EXISTS bezpośrednio?

186

Zastanawiałem się, czy można zrobić coś takiego (co nie działa):

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

Wydaje się, że powinno to być wykonalne, ale wiele rzeczy, które powinny działać w SQL, nie;) Widziałem obejścia tego problemu (WYBIERZ 1, gdzie ... Istnieje ...), ale wydaje się, że powinienem móc po prostu rzutuj nieco wynik istniejącej funkcji i zakończ ją.

jcollum
źródło

Odpowiedzi:

267

Nie, musisz użyć obejścia.

Jeśli musisz zwrócić bit warunkowy 0/1, innym sposobem jest:

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

Lub bez obsady:

SELECT
   CASE
       WHEN EXISTS( SELECT 1 FROM theTable WHERE theColumn LIKE 'theValue%' )
            THEN 1 
       ELSE 0 
   END
Alex K.
źródło
16
Nie potrzebujesz rzutowania, jeśli zapisujesz wynik w typie danych Bit, ponieważ rzutowanie jest już niejawne.
MikeTeeVee,
3
Właśnie przetestowałem tę technikę, działa świetnie. Opcja CAST to BIT nie jest konieczna do uzyskania wyników z zapytania, przetestowanego z SQL Server 2008 R2.
Tore Aurstad
W moim przypadku obsada MUSI zostać usunięta
Sérgio S. Filho
51
SELECT CAST(COUNT(*) AS bit) FROM MyTable WHERE theColumn like 'theValue%'

Kiedy rzucisz na bit

  • 0 -> 0
  • wszystko inne -> 1
  • I NULL -> NULL oczywiście, ale nie możesz uzyskać NULL z COUNT (*) bez GROUP BY

bitmapuje bezpośrednio na booleantypy danych .net, nawet jeśli tak naprawdę nie jest ...

Wygląda podobnie, ale nie daje wiersza (nie zero), jeśli nie pasuje, więc nie jest taki sam

SELECT TOP 1 CAST(NumberKeyCOlumn AS bit) FROM MyTable WHERE theColumn like 'theValue%'
gbn
źródło
4
Ale to wcale nie używa EXISTS. Nie pytałam, jak to obejść, mogę znaleźć obejścia, pytałam, czy istnieje jakaś sztuczka w użyciu, jeśli nie jestem tego świadomy.
jcollum
6
To nie jest obejście, to jeden prawidłowy sposób. ISTNIEJE to obejście ... I bardzo czyste, nie?
gbn
1
@jcollum: tak lub coś takiego. ISTNIEJE prawie zawsze, JEŚLI
ISTNIEJE LUB
14
EXISTS jest bardziej wydajny niż COUNT podczas sprawdzania istnienia rekordu - patrz sqlblog.com/blogs/andrew_kelly/archive/2007/12/15/…
Tahir Hassan
9
W przeciwieństwie do tego EXISTS, COUNTnadal szuka danych w celu dopasowania wierszy nawet po znalezieniu pierwszego, ponieważ musi zostać policzony.
IsmailS
11

Trochę spóźniłem się z tym; potknąłem się o słupek. Oto jednak rozwiązanie, które jest bardziej wydajne i schludne niż wybrana odpowiedź, ale powinno zapewniać tę samą funkcjonalność:

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
źródło
7

Możesz użyć IIFiCAST

SELECT CAST(IIF(EXISTS(SELECT * FROM theTable 
                       where theColumn like 'theValue%'), 1, 0) AS BIT)
Jaider
źródło
1
Podoba mi się to, ale działa tylko w SQL Server 2012 i nowszych wersjach. Wygląda na to, że IIF został dodany w 2012 roku
ja928,
5

Możesz także wykonać następujące czynności:

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

Jeśli nie ma wartości zaczynających się od „theValue”, to zwróci null (brak rekordów) zamiast nieco 0

Nelson
źródło
2

Nie, to nie jest możliwe. Bitowy typ danych nie jest typem danych boolowskich. Jest to całkowity typ danych, który może wynosić 0,1 lub NULL.

Martin Smith
źródło
3
@bzlm Tak, może w SQLServer od ponad 10 lat. SQL Server 7.0 wprowadził to msdn.microsoft.com/en-us/library/aa237157%28SQL.80%29.aspx
Martin Smith
4
@bzlm - Wygląda na to, że ściskasz słomki i tak naprawdę nie wiesz nic o typach danych programu SQL Server. Definicja bitu w SQL Server to „Całkowity typ danych, który może przyjmować wartość 1, 0 lub NULL”. msdn.microsoft.com/en-us/library/ms177603.aspx . Dotyczy to kolumn i zmiennych Transact SQL. Nigdzie nie można użyć zmiennej bitowej jako wartości boolowskiej w SQL, IF(@TRUE)na przykład, ani odwrotnie, wyrażenie boolowskie nie może zostać trochę zmienione . (Z np. SET @BitVariable = (1=1))
Martin Smith
1
Widzę, dokąd zmierzasz, ale rzutowanie na bit nie było tak dużym problemem, jak możliwość bezpośredniego wyboru EXISTS.
jcollum
1

Innym rozwiązaniem jest użycie ISNULLw połączeniu z SELECT TOP 1 1:

SELECT ISNULL((SELECT TOP 1 1 FROM theTable where theColumn like 'theValue%'), 0)
anar khalilov
źródło
-1

Wierzę , że istnieje można użyć tylko w klauzuli where, więc będziesz musiał zrobić obejście (lub podzapytanie, w którym istnieje klauzula where). Nie wiem, czy to się liczy jako obejście.

A co z tym:

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
źródło
A co ze sprawą, kiedy jest wybrany?
lowerkey
-1
SELECT IIF(EXISTS(SELECT * FROM theTable WHERE theColumn LIKE 'theValue%'), 1, 0)
MEC
źródło