Вернуть значение, если строки не найдены SQL - PullRequest
78 голосов
/ 21 апреля 2010

Вот мой простой запрос. Если я сделаю запрос на запись, которая не существует, я ничего не получу. Я предпочел бы, чтобы false (0) возвращалось в этом сценарии. Ищите простой способ для учета отсутствия записей.

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

Ответы [ 10 ]

101 голосов
/ 21 апреля 2010

Это похоже на Адама Робинсона, но использует ISNULL вместо 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)

Если во внутреннем запросе есть соответствующая строка, возвращается 1. Внешний запрос (с ISNULL) затем возвращает это значение 1. Если у внутреннего запроса нет соответствующей строки, то он ничего не возвращает. Внешний запрос обрабатывает это как NULL, поэтому ISNULL возвращает 0.

59 голосов
/ 21 апреля 2010
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)
15 голосов
/ 21 июня 2012

Это может быть мертвая лошадь, еще один способ вернуть 1 строку, если строк не существует, - это UNION другой запрос и отображение результатов, если в таблице их нет.

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
) 
9 голосов
/ 12 февраля 2014

Что-то вроде:

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 голосов
/ 26 марта 2015

Я прочитал все ответы здесь, и потребовалось некоторое время, чтобы понять, что происходит. Нижеследующее основано на ответе Мо Сиско и некоторых связанных исследованиях

Если ваш запрос SQL не возвращает никаких данных, поле с нулевым значением отсутствует, поэтому ни ISNULL, ни COALESCE не будут работать так, как вы этого хотите. Используя подзапрос, запрос верхнего уровня получает поле с нулевым значением, и ISNULL, и COALESCE будут работать так, как вы хотите / ожидаете.

Мой запрос

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

Мой запрос с комментариями

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 голосов
/ 06 января 2015

Вам нужно только заменить ГДЕ ЛЕВЫМ СОЕДИНЕНИЕМ:

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

Это решение позволяет также возвращать значения по умолчанию для каждого столбца, например:

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 ...
5 голосов
/ 21 апреля 2010

Нет совпадений означает, что запись не возвращена. Нет места для значения «0», если записи не найдены. Вы можете создать сумасшедший запрос UNION, чтобы делать то, что вы хотите, но намного, намного, намного лучше, просто проверив количество записей в наборе результатов.

1 голос
/ 25 августа 2016

А как насчет галстуков?

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]
0 голосов
/ 28 февраля 2019
Ключ

@ hai-phan с использованием LEFT JOIN является ключевым, но за ним может быть немного трудно следовать. У меня был очень сложный запрос, который также может ничего не возвращать. Я просто упростил его ответ следующим образом для моих нужд. Легко применить к запросу со многими столбцами.

;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 голосов
/ 04 декабря 2015

Это может быть один путь.

SELECT TOP 1 [Column Name] FROM (SELECT [Column Name] FROM [table]
    WHERE [conditions]
    UNION ALL
    SELECT 0 )A ORDER BY [Column Name] DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...