2011-03-15 71 views
4

假设我有一个SQL表与此架构:SQL SELECT具有缺省值

CREATE TABLE(
foo INTEGER, 
bar INTEGER, 
baz INTEGER DEFAULT 0 
); 

包含数据

foo|bar|baz 
----------- 
1 |1 |2 
2 |3 |4 

和我对用于foo和1值1,2, 2,3代表bar。是否有SQL请求会返回“丢失”值以及现有值:

foo|bar|baz 
----------- 
1 |1 |2 
1 |2 |0 
1 |3 |0 
2 |1 |0 
2 |2 |0 
2 |3 |4 

?我怀疑没有,但也许我只是不知道它?

更新: 1)使用SQLite 3; 2)缺失值由DEFAULT条款给出; 3)第二张表显示预期的结果。

+0

您正在使用哪个数据库管理系统? –

+0

什么是确定“缺失”值的逻辑? – Ronnis

+0

“缺失值”是什么意思? – gnuchu

回答

4

假设你命名你的表Data,下面会得到你,你已经发布的结果。

  • 语句在内存表中创建一个临时表,其中包含从1到实际表中的最大值的所有Bar。
  • CROSS APPLY会为您的表中是否存在的每个小节返回一行。
  • CASE语句选择存在的baz(如果存在),如果不存在则选择0。

SQL语句

WITH q AS (
    SELECT [bar] = 1 
      , [MaxBar] = MAX(bar) 
    FROM Data 
    UNION ALL 
    SELECT q.bar + 1 
      , q.MaxBar 
    FROM q 
    WHERE q.bar + 1 <= q.MaxBar 
) 
SELECT Data.foo 
     , q.bar 
     , CASE WHEN q.bar = Data.bar THEN Data.baz ELSE 0 END 
FROM q 
     CROSS APPLY Data 
ORDER BY 
     Data.foo 
     , q.bar 

测试脚本

WITH Data AS (
    SELECT [foo] = 1, [bar] = 1, [baz] = 2 
    UNION ALL SELECT 2, 3, 4 
), q AS (
    SELECT [bar] = MIN(bar) 
      , [MaxBar] = MAX(bar) 
    FROM Data 
    UNION ALL 
    SELECT q.bar + 1 
      , q.MaxBar 
    FROM q 
    WHERE q.bar + 1 <= q.MaxBar 
) 
SELECT Data.foo 
     , q.bar 
     , CASE WHEN q.bar = Data.bar THEN Data.baz ELSE 0 END 
FROM q 
     CROSS APPLY Data 
ORDER BY 
     Data.foo 
     , q.bar 
+0

@Alexey,我已经稍微改变了语句从1 io MIN(bar)开始,以防MIN(bar)会不同于1。 –

2

创建下表

table_foo

foo| 
----------- 
1 | 
2 | 

table_bar

bar| 
----------- 
1 | 
2 | 
3 | 

之后,这个查询应该做的伎俩:

select * from table 
UNION 
(
    select 
     table_foo.foo, 
     table_bar.bar, 
     0 
    from 
     table, 
     table_foo, 
     table_bar 
    where 
     table.foo != table_foo.foo and 
     table.bar != table_bar.bar 
) 
+0

@Shamit THIS不起作用。 'Baz'将总是返回0 – Curt

+0

@Curt,这应该是可以预料的,因为在Baz问题中,除了已经存在的行以外的所有行都是零。 –

+0

@Shamit在最初的问题中,当foo = 1&bar = 1时,baz = 2。我不认为你的例子是这样的 – Curt

1

假设你的标签乐被称为MYTAB,这个SQL会产生数据的第二个表(我假设MSSQL):

select 
    f.foo, 
    b.bar, 
    baz = coalesce(m.baz,0) 
from 
    (select foo = 1 union select foo = 2) f 
    cross join (select bar = 1 union select bar = 2 union select bar = 3) b 
    left join mytab m on f.foo = m.foo and b.bar = m.bar 
+0

我认为Alexey需要一个解决方案表中的任何行都存在。此解决方案可行,但每次更改或添加行时都需要进行调整。 –

+0

@Lieven - 只是工作的规范! - “我对foo和1,2,3的值为1,2的值感兴趣”。我喜欢你的解决方案作为一个普遍的例子,但是如果他只有这些可能的价值,那么更简单的解决方案是最好的。 –

+0

遵循你的逻辑,'选择1,1,2联合所有选择1,2,0联合... ...'甚至会更简单。 –

1
declare @foovalues table (foo int) -- values 1,2 for foo 
insert into @foovalues values (1) 
insert into @foovalues values (2) 

declare @barvalues table (bar int) -- values 1,2,3 for bar 
insert into @barvalues values (1) 
insert into @barvalues values (2) 
insert into @barvalues values (3) 

declare @table table (foo int, bar int, baz int) -- your data 
insert into @table values (1,1,2) 
insert into @table values (2,3,4) 

select x.foo, x.bar, isnull(baz, 0) as baz 
from (select f.foo, b.bar from @foovalues f, @barvalues b) as x 
left outer join @table t on t.foo = x.foo and t.bar = x.bar 
order by x.foo, x.bar