Добавить пустую строку в результаты запроса, если результатов не найдено - PullRequest
21 голосов
/ 29 июля 2010

Я пишу хранимые процедуры, которые вызываются устаревшей системой.Одно из ограничений унаследованной системы заключается в том, что в одном наборе результатов, возвращаемом из сохраненного процесса, должна быть хотя бы одна строка.Стандарт заключается в том, чтобы возвращать ноль в первом столбце (да, я знаю!).

Очевидный способ добиться этого - создать временную таблицу, поместить в нее результаты, проверить все строки во временной переменной.table и либо возвращает результаты из временной таблицы, либо из одного пустого результата.

Другой способ может заключаться в том, чтобы выполнить EXISTS для того же предложения where, которое находится в главном запросе, перед выполнением основного запроса.

Ни то, ни другое не очень приятно.Может ли кто-нибудь придумать лучший способ.Я размышлял в духе UNION вроде этого (я знаю, это не работает):

--create table #test
--(
--  id int identity,
--  category varchar(10)
--)
--go
--insert #test values ('A')
--insert #test values ('B')
--insert #test values ('C')

declare @category varchar(10)

set @category = 'D'

select
    id, category
from #test
where category = @category
union
select
    0, ''
from #test
where @@rowcount = 0

Ответы [ 6 ]

29 голосов
/ 29 июля 2010

Боюсь, очень мало вариантов.

Вы всегда должны касаться стола дважды, будь то COUNT, EXISTS before, EXISTS в UNION, предложение TOP и т. Д.

select
    id, category
from mytable
where category = @category
union all --edit, of course it's quicker
select
    0, ''
where NOT EXISTS (SELECT * FROM mytable where category = @category)

EXISTSРешение лучше, чем COUNT, потому что оно остановится, когда найдет строку.COUNT будет пересекать все строки, чтобы фактически посчитать их

12 голосов
/ 15 сентября 2015

Это старый вопрос, но у меня была такая же проблема. Решение действительно простое, БЕЗ двойного выбора:

select top(1) WITH TIES * FROM (
select
id, category, 1 as orderdummy
from #test
where category = @category
union select 0, '', 2) ORDER BY orderdummy

с помощью «С TIES» вы получаете ВСЕ строки (все имеют 1 как «orderdummy», поэтому все являются связями), или, если результата нет, вы получаете значение по умолчанию.

3 голосов
/ 05 мая 2016

Это ответ @ swe, только лучше отформатированный.

CREATE FUNCTION [mail].[f_GetRecipients]
(
    @MailContentCode VARCHAR(50)
)
RETURNS TABLE
AS
RETURN
(
    SELECT TOP 1 WITH TIES -- returns all rows having highest priority found
        [To],
        CC,
        BCC
    FROM (
        SELECT
            [To],
            CC,
            BCC,
            1 AS Priority -- if no rows, priority 2 under UNION will get returned
        FROM mail.Recipients
        WHERE 1 = 1
            AND IsActive = 1
            AND MailContentCode = @MailContentCode

        UNION ALL

        SELECT
            *
        FROM (VALUES
            (N'system@company.com', NULL, NULL, 2),
            (N'author@company.com', NULL, NULL, 2)
        ) defaults([To], CC, BCC, Priority)
    ) emails
    ORDER BY Priority
)
3 голосов
/ 18 октября 2011

Вы можете использовать полное внешнее соединение. Что-то с эффектом ...

declare @category varchar(10)

set @category = 'D'

select #test.id, ISNULL(#test.category, @category) as category from (
    select
        id, category
    from #test
    where category = @category
)  
FULL OUTER JOIN (Select @category as CategoryHelper ) as EmptyHelper on 1=1   

В настоящее время я тестирую этот сценарий на производительность, поэтому не уверен, какое влияние это окажет, но он даст вам пустую строку с заполненной категорией.

1 голос
/ 25 апреля 2014

Чтобы не дублировать выбранный запрос, как насчет временной таблицы, чтобы сначала сохранить результат запроса? И, основываясь на временной таблице, вернуть строку по умолчанию, если временная таблица пуста, или вернуть временную, если она имеет результат?

1 голос
/ 29 июля 2010

Полагаю, вы могли бы попробовать:

Declare @count int
set @count = 0

Begin
Select @count = Count([Column])
From //Your query

if(@Count = 0) 
   select 0
else //run your query

Недостатком является то, что вы эффективно выполняете свой запрос дважды, а преимуществом является то, что вы пропускаете временную таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...