Zwróć wartość, jeśli nie znaleziono żadnych wierszy w Microsoft tSQL

97

Używając wersji SQL firmy Microsoft , oto moje proste zapytanie. Jeśli zapytam o rekord, który nie istnieje, nic nie zostanie zwrócone. Wolałbym, aby w tym scenariuszu zwracano wartość false (0). Poszukiwanie najprostszej metody na zlikwidowanie rekordów.

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

Odpowiedzi:

66
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
źródło
Poniższe zapytanie zwraca jedną wartość w warunku else, ale najlepiej powinno zwracać wiele wartości. wybierz przypadek, gdy count (QTIB_REQ _) <1 then 0 else QTIB_REQ_ kończy się od qb_requisitions_all gdzie QTIB_REQ_ IN ($ Req_disabled_WA) i CLIENT___BENCH___NON_BILLABLE NOT IN ('Non-Billable', 'Non-Billable', 'NonBillable', SC Cleared Strategic Hires ',' Bench / US project ') i DATEDIFF (CURDATE (), TARGET_FILL_DATE) <60 i DATEDIFF (CURDATE (), TARGET_FILL_DATE)> 0
Praneet Bahadur
125

Jest to podobne do Adama Robinsona, ale używa ISNULL zamiast 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)

Jeśli zapytanie wewnętrzne ma pasujący wiersz, zwracana jest 1. Zapytanie zewnętrzne (z ISNULL) zwraca następnie tę wartość 1. Jeśli zapytanie wewnętrzne nie ma pasującego wiersza, to nic nie zwraca. Zapytanie zewnętrzne traktuje to jak NULL, więc ISNULL w końcu zwraca 0.

Moe Sisko
źródło
2
Dziękujemy za dodanie tego! To jest dokładnie to, czego potrzebuję, ponieważ mogłem po prostu SELECT ISNULL ((SELECT Id ... zamiast 1, aby uzyskać dane, których szukałem!
Jesse Smith
3
Wiem, że bardzo późno, ale możesz zastąpić ISNULL COALESCE, aby osiągnąć ten sam wynik.
BlueChippy
2
Nabrałem zwyczaju używania COALESCE zamiast ISNULL, ponieważ z pamięci (przyzwyczajenia trudno umrzeć), ISNULL nie jest dostępny w SQL Lite lub jak to się nazywa, co działa na starszych urządzeniach z systemem Windows Mobile. COALESCE działa zarówno na wersji Lite, Express, jak i na pełnym SQL.
Reklamy
1
Działa lepiej, jeśli chcesz uzyskać wartość zmiennej zamiast 0 lub 1. Zapytanie Adama wymaga grupowania lub czegoś w tym rodzaju.
Drac
@MoeSisko Podoba mi się, jak zwraca 0, jeśli jest null, ale zamiast zwracać 1, jak mogę sprawić, aby zwrócił wartość z tabeli?
Michael
21

Może to być martwy koń. Innym sposobem na zwrócenie 1 wiersza, gdy nie ma żadnych wierszy, jest wysłanie do UNION innego zapytania i wyświetlenie wyników, jeśli nie istnieją w tabeli.

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
) 
anAgent
źródło
2
Użyłem podobnej metody, próbując uzyskać sumy z zapytania. Po prostu utworzyłem unię z zapytaniem, które zwróciło 0 ( SELECT 0), a następnie zrobiłem SUMna tej unii. Proste i łatwe do naśladowania.
cjbarth
2
Jeśli zwróci 2 wiersze, czy gwarantuje, że wiersze zostaną zwrócone w oczekiwanej kolejności?
Sarsaparilla
I jest ciężki dla planu wykonania
Fandango68
13

Coś jak:

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
źródło
Użyłem tego rozwiązania, ponieważ ma to dla mnie więcej sensu (tradycyjnie nie jestem użytkownikiem SQL), jednak używam SQL Server, stwierdziłem, że dodanie nazwy col do tego rozwiązania ładnie zaokrągliło to rozwiązanie. czyli po twoim select 1i select 2dodanym as <colName>
Harvey
8

Przeczytałem wszystkie odpowiedzi tutaj i zajęło trochę czasu, zanim zrozumiałem, co się dzieje. Poniższe informacje oparte są na odpowiedzi udzielonej przez udzielonej Moe Sisko i kilku powiązanych badaniach

Jeśli zapytanie SQL nie zwraca żadnych danych, nie ma pola z wartością null, więc ani ISNULL, ani COALESCE nie będą działać tak, jak chcesz. Używając zapytania podrzędnego, zapytanie najwyższego poziomu pobiera pole z wartością null, a zarówno ISNULL, jak i COALESCE będą działać tak, jak chcesz / oczekujesz.

Moje zapytanie

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

Moje zapytanie z komentarzami

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

Musisz tylko zamienić GDZIE na 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

To rozwiązanie pozwala również zwrócić domyślne wartości dla każdej kolumny, na przykład:

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

Brak dopasowanego rekordu oznacza, że ​​żaden rekord nie został zwrócony. Nie ma miejsca dla „wartości” 0, jeśli nie zostaną znalezione żadne rekordy. Możesz utworzyć szalone zapytanie UNION, aby zrobić to, co chcesz, ale o wiele, dużo, dużo lepiej po prostu sprawdzić liczbę rekordów w zestawie wyników.

Larry Lustig
źródło
Obecnie tym się zajmuję. Sprawdź, czy liczba rekordów jest pusta, czy nie. Pomyślałem, że to może być sposób na skrócenie mojego czeku.
Matt
Niektóre aplikacje nie pozwalają na „proste” sprawdzenie
Nadia Solovyeva
3

To może być w jedną stronę.

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
źródło
Podoba mi się to podejście. Wydaje mi się, że wyrażanie domyślnych danych jest nieco czystsze, zwłaszcza jeśli otrzymujesz wiele kolumn danych / wartości domyślnych.
Mark At Ramp51
Lol, to najlepsze i najczystsze rozwiązanie
Kyle Bridenstine
1

A co z Krawatami?

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
źródło
1
DECLARE @col int; 
select @col = id  FROM site WHERE status = 1; 
select coalesce(@col,0);
czarny
źródło
1

Odpowiedź @ hai-phan LEFT JOINjest kluczem, ale może być trochę trudna do zrozumienia. Miałem skomplikowane zapytanie, które również może nic nie zwrócić. Po prostu uprościłem jego odpowiedź na moją potrzebę. Do zapytania z wieloma kolumnami można łatwo zastosować.

;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

Aktualizacja: ta odpowiedź w SqlServerCentral jest najlepsza. Wykorzystuje tę funkcję MAX - „MAX zwraca NULL, gdy nie ma wiersza do wybrania”.

SELECT ISNULL(MAX(value), 0) FROM table WHERE Id = @SiteId
Weihui Guo
źródło
1
Zaktualizowana odpowiedź działa.
Andrew Cowenhoven
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ş
źródło