Union ALL获取空行

时间:2012-07-11 12:34:32

标签: sql sql-server union

我有两个查询加入了union All

SELECT  select 'Finished' AS Status,amount AS amount,units As Date
from table1 WHERE Pdate > cdate AND name =@name
UNION ALL
SELECT  select 'Live' AS Live,amount,units 
from table1  Where Pdate = cdate And name =@name

结果

Status     amount   units
Finished     100    20
Live         200    10

当任一查询提取空集时,我只得到一行,如果两者都取空集,那么我没有行

那么我怎样才能得到这样的结果

Status     amount   Units
Finished     100    20
Live         0      0

OR

Status     amount   Units
Finished     0      0
Live         200    10

OR

Status     amount   Units
Finished      0          0
Live          0          0

感谢。

3 个答案:

答案 0 :(得分:1)

我认为你可以使用总和来做到这一点?如果sum在没有行时不返回0,则替换为Coalesce(sum(amount), 0) as amount

SELECT  select 'Finished' AS Status,sum(amount) AS amount, sum(units) As Unit
from table1 WHERE Pdate > cdate AND name =@name
UNION ALL
SELECT  select 'Live' AS Status, sum(amount) as amount, sum(units) as Unit
from table1  Where Pdate = cdate And name =@name

如果你不想对结果求和那么只需要合并就可以了吗? coalesce(amount, 0) As amount等......

答案 1 :(得分:0)

我只是想指出你的查询是不必要的复杂,嵌套选择和联合all。编写查询的更好方法是:

select (case when pdate > cdate then 'Finished' else 'Live' end) AS Status,
        amount AS amount, units As Date
from table1
WHERE Pdate >= cdate AND name = @name

此查询不会产生您想要的内容,因为它只生成有数据的行。

获取额外行的一种方法是扩充原始数据,然后检查是否需要。

select status, amount, units as Date
from (select Status, amount, units,
             row_number() over (partition by status order by amount desc, units desc) as seqnum
      from (select (case when pdate > cdate then 'Finished' else 'Live' end) AS Status,
                    amount, units, name
            from table1
            WHERE Pdate >= cdate AND name = @name
           ) union all
           (select 'Finished', 0, 0, @name
           ) union all
           (select 'Live', 0, 0, @name
           )
          ) t
where (amount > 0 or units > 0) or
      (seqnum = 1)

这会添加您想要的额外行。然后它会枚举它们,所以它们会以任何顺序排在最后。它们被忽略,除非它们是序列中的第一个。

答案 2 :(得分:0)

尝试这样的事情

with stscte as
(
select 'Finished' as status
union all 
select 'Live'
),
datacte
as(
select 'Finished' AS Status,amount AS amount,units As Date 
from table1 WHERE Pdate > cdate AND name =@name 
UNION ALL 
select 'Live' ,amount,units  
from table1  Where Pdate = cdate And name =@name 
)
select sc.status,isnull(dc.amount,0) as amount,isnull(dc.unit,0) as unit 
from stscte sc left join   datacte dc
on sc.status = dc.status