选择不存在的行

时间:2014-05-07 12:32:38

标签: sql sql-server sql-server-2008 sql-server-2005 sql-server-2008-r2

假设我有一张桌子:

ColumnA       ColumnB
---------------------------------
1             10.75
4             1234.30
6             2000.99

如何编写将导致以下结果的SELECT查询:

ColumnA    ColumnB
---------------------------------
1             10.75
2             0.00
3             0.00
4             1234.30
5             0.00
6             2000.99

6 个答案:

答案 0 :(得分:7)

您可以使用CTE创建表格中从1到最大值的数字列表:

; with  numbers as
        (
        select  max(ColumnA) as nr
        from    YourTable
        union all
        select  nr - 1
        from    numbers
        where   nr > 1
        )
select  nr.nr as ColumnA
,       yt.ColumnB
from    numbers nr
left join
        YourTable yt
on      nr.nr = yt.ColumnA
order by
        nr.nr
option  (maxrecursion 0)

See it working at SQL Fiddle.

答案 1 :(得分:1)

请尝试:

declare @min int, @max int
select @min=MIN(ColumnA), @max=MAX(ColumnA) from tbl

select 
    distinct number ColumnA, 
    isnull(b.ColumnB, 0) ColumnB
from 
    master.dbo.spt_values a left join tbl b on a.number=b.ColumnA
where number between @min and @max

答案 2 :(得分:0)

创建TallyTable(或NumbersTable) - 请参阅此问题:What is the best way to create and populate a numbers table?

使用该表创建一个insert语句:

INSERT INTO YourTable (ColumnA, ColumnB)
SELECT Number FROM NumberTable
WHERE
    NOT EXISTS (SELECT 1 FROM YourTable WHERE NumberTable.Number = YourTable.ColumnA)
    -- Adjust this value or calculate it with a query to the maximum of the source table
    AND NumberTable.Number < 230130

答案 3 :(得分:0)

DECLARE @t TABLE (ID INT,Val DECIMAL(10,2))
INSERT INTO @t (ID,Val) VALUES (1,10.75)
INSERT INTO @t (ID,Val) VALUES (4,6.75)
INSERT INTO @t (ID,Val) VALUES (7,4.75)
declare @MinNo int
declare @MaxNo int
declare @IncrementStep int
set @MinNo = 1
set @MaxNo = 10
set @IncrementStep = 1

;with C as
(
  select @MinNo as Num
  union all 
  select Num + @IncrementStep
  from C 
  where Num < @MaxNo
)      
select Num,
CASE WHEN Val IS NOT NULL THEN Val ELSE 0.00 END AS NUMBER
from C  
LEFT JOIN @t t
ON t.ID = c.Num

答案 4 :(得分:0)

您可以使用数字表或以下技巧生成一个序列,您可以LEFT OUTER JOIN使用您的表格。我假设您想要动态确定边界:

WITH Seq AS 
(
    SELECT TOP ((SELECT Max(ColumnA)FROM Table1) - (SELECT Min(ColumnA) FROM Table1) + 1) 
        Num = (SELECT Min(ColumnA) FROM Table1)+ Row_number() OVER (ORDER BY [object_id]) -1
    FROM   sys.all_objects) 
SELECT ColumnA = Seq.Num,
       ColumnB = COALESCE(t.ColumnB ,0.00)
FROM   Seq 
LEFT OUTER JOIN Table1 t
    ON Seq.Num = t.ColumnA 

Demo带样品。

值得一读:http://www.sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1

答案 5 :(得分:0)

我收集了类似这样的表函数。

create function dbo.GetNumbers(@Start int, @End int)
returns @Items table
(
    Item int
)
as 
begin

    while (@Start <= @End)
    begin 
        insert into @Items
        values (@Start)

        set @Start = @Start + 1
    end 

    return

end

然后我可以用它来连接到我的数据表,每个值都会在那里。

declare @min int, @max int
set @min = 10
set @max = 20


select gn.Item
from dbo.GetNumbers(@min, @max) gn

我有类似日期范围,时间,时区等的表函数。