2011-03-15 129 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