如果未找到任何结果,请在查询结果中添加空行

时间:2010-07-29 18:13:27

标签: sql sql-server sql-server-2005 tsql

我正在编写由遗留系统调用的存储过程。遗留系统的一个约束是从存储过程返回的单个结果集中必须至少有一行。标准是在第一列中返回零(是的,我知道!)。

实现这一目标的显而易见的方法是创建临时表,将结果放入其中,测试临时表中的任何行,并从临时表或单个空结果返回结果。

另一种方法可能是在执行主查询之前对主查询中的相同where子句执行EXISTS。

这些都不令人满意。任何人都可以想到更好的方法。我正在考虑像这样的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 个答案:

答案 0 :(得分:29)

恐怕很少有选择。

你总是要触摸两次表,无论是COUNT,之前的EXISTS,UNION中的EXIST,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将遍历所有行以实际计算它们

答案 1 :(得分:12)

这是一个老问题,但我遇到了同样的问题。 解决方案非常简单,无需双重选择:

select top(1) WITH TIES * FROM (
select
id, category, 1 as orderdummy
from #test
where category = @category
union select 0, '', 2) ORDER BY orderdummy
" WITH TIES"你得到所有行(所有行都有1作为" orderdummy",所以都是关系),或者如果没有结果,你得到你的默认行。

答案 2 :(得分:3)

您可以使用完整的外部联接。有什么影响......

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   

目前我自己正在对这个场景进行性能测试,因此不确定会产生什么样的影响,但它会给你一个填充了Category的空白行。

答案 3 :(得分:3)

这是@ 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
)

答案 4 :(得分:1)

我想你可以试试:

Declare @count int
set @count = 0

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

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

缺点是你有效地运行了两次查询,更重要的是你正在滑动临时表。

答案 5 :(得分:1)

为避免重复选择查询,临时表如何先存储查询结果?并且基于临时表,如果临时表为空,则返回默认行;如果有结果,则返回临时值?