Вернуть значение, если в Microsoft tSQL не найдено строк


97

Вот мой простой запрос, использующий версию SQL от Microsoft . Если я запрошу запись, которой не существует, я ничего не получу. Я бы предпочел, чтобы в этом сценарии возвращалось 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

Ответы:


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)

Ниже запрос возвращает одно значение в условии else, но в идеале он должен возвращать несколько значений. выберите случай, когда count (QTIB_REQ _) <1, затем 0 иначе QTIB_REQ_ end from qb_requisitions_all, где QTIB_REQ_ IN ($ Req_disabled_WA) и CLIENT___BENCH___NON_BILLABLE NOT IN ('Non-Billable', 'Non-Billable', 'Non-Billable', 'Non-Billable', 'Non-Billable', 'Non-Billable', 'Bench SC Cleared Strategic Hires ',' Bench / US project ') и DATEDIFF (CURDATE (), TARGET_FILL_DATE) <60 и DATEDIFF (CURDATE (), TARGET_FILL_DATE)> 0
Пранит Бахадур

125

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


2
Спасибо, что добавили это! Это именно то, что мне нужно, так как я мог бы просто SELECT ISNULL ((SELECT Id ... вместо 1, чтобы получить данные, которые я искал!
Джесси Смит

3
Я знаю, что очень поздно, но вы можете заменить ISNULL на COALESCE, чтобы получить тот же результат.
BlueChippy 03

2
У меня появилась привычка использовать COALESCE, а не ISNULL, потому что по памяти (от привычек трудно избавиться) ISNULL недоступен в SQL Lite или как там он называется, что работает на старых устройствах Windows Mobile. COALESCE работает как с облегченным, так и с Express и полноценным SQL.
Ads

1
Он работает лучше, если вы хотите получить значение переменной вместо 0 или 1. Запрос Адама требует группировки или чего-то в этом роде.
Драк

@MoeSisko Мне нравится, как он возвращает 0, если он равен нулю, но вместо того, чтобы возвращать 1, как я могу заставить его вернуть значение из таблицы?
Майкл

21

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

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
) 

2
Я использовал аналогичный метод при попытке получить итоги по запросу. Я просто выполнил объединение с запросом, который вернул 0 ( SELECT 0), а затем сделал SUMобъединение. Просто и понятно.
cjbarth

2
Если он возвращает 2 строки, гарантируется ли, что строки будут возвращены в ожидаемом порядке?
Sarsaparilla

И это тяжело по плану исполнения
Fandango68

13

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

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

Я использовал это решение, поскольку оно имеет для меня больше смысла (я традиционно не являюсь пользователем SQL). Тем не менее, я использую SQL Server, я обнаружил, что добавление имени столбца к этому решению хорошо округляет. то есть после того как ваш , select 1и select 2я добавилas <colName>
Харви

8

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

Если ваш 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

Вам нужно только заменить WHERE на 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

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

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 ...

4

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


В настоящее время я этим занимаюсь. Проверьте, какой счетчик записей пуст или нет. Подумал, что они, возможно, были способом сократить мой чек.
Мэтт

Некоторые приложения не позволяют «просто» проверить
Надя Соловьева

3

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

SELECT TOP 1 [Column Name] FROM (SELECT [Column Name] FROM [table]
    WHERE [conditions]
    UNION ALL
    SELECT 0 )A ORDER BY [Column Name] DESC

Мне нравится такой подход. Мне кажется, что это немного чище при выражении данных по умолчанию, особенно если в итоге вы получаете множество столбцов данных / значений по умолчанию.
Mark At Ramp51

Лол, это лучшее и самое чистое решение
Кайл Бриденстайн,

1

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

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]


1

Ответ @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

Обновление: этот ответ на SqlServerCentral - лучший. Он использует эту функцию MAX - «MAX возвращает NULL, если нет строки для выбора».

SELECT ISNULL(MAX(value), 0) FROM table WHERE Id = @SiteId

1
Обновленный ответ работает.
Эндрю Коуэнховен,

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.