Tsql 返回空值之前的上一个值

Tsql 返回空值之前的上一个值,tsql,sql-server-2017,Tsql,Sql Server 2017,我当前正在查询一个缺少索引的表 以下是一些示例数据: id dStartDate 126 2010-04-22 00:00:00.000 127 NULL 128 2010-04-29 00:00:00.000 129 2010-05-03 00:00:00.000 130 NULL 131 NULL 132 NULL 133 2010-04-29 00:00:00.000 134 NULL 135 NULL 136 2010-04-29 00:00:00.000 137 NULL 138 N

我当前正在查询一个缺少索引的表

以下是一些示例数据:

id  dStartDate
126 2010-04-22 00:00:00.000
127 NULL
128 2010-04-29 00:00:00.000
129 2010-05-03 00:00:00.000
130 NULL
131 NULL
132 NULL
133 2010-04-29 00:00:00.000
134 NULL
135 NULL
136 2010-04-29 00:00:00.000
137 NULL
138 NULL
139 2010-04-29 00:00:00.000
140 NULL
141 2010-04-29 00:00:00.000
142 2010-04-29 00:00:00.000
143 NULL
144 NULL
我使用以下脚本获取缺少的索引:

declare @id int
declare @maxid int

set @id = 1
select @maxid = max(idJCMaster) from _btblJCMaster

declare @IDseq table    (id int)

while @id < @maxid --whatever you max is
begin
    insert into @IDseq values(@id)

    set @id = @id + 1
end

select 
    s.id
from        @IDseq s 
left join   _btblJCMaster t on s.id = t.idJCMaster
where t.idJCMaster is null

没有其他更简单的方法来实现这一点吗?

您可以在下面的查询中尝试-

SELECT id, (SELECT MAX(dStartDate)
            FROM YOUR_TABLE
            WHERE id >= t1.id) dStartDate
FROM YOUR_TABLE t1;

您可以尝试以下方法:

首先,我们需要一个模型表来模拟您的问题。请在下一个问题中自己提供。最好提供一个自运行、独立的示例,包括DDL、INSERT和您自己的尝试。这种模拟被称为

-询问

WITH cte AS(SELECT id,dStartDate FROM @tbl WHERE dStartDate IS NOT NULL)
SELECT t.id 
      ,A.gaplessStartDate
FROM @tbl t
CROSS APPLY(SELECT TOP 1 cte.dStartDate 
            FROM cte 
            WHERE cte.id<=t.id 
            ORDER BY cte.id DESC) A(gaplessStartDate);
简而言之:

我们首先使用CTE来获取一个仅包含非空行的集合。 现在,我们可以使用APPLY通过调用按降序排序的最上面的小id来获取fitting行和id

这种方法有点像一种新方法。任何一行都需要一个具有ORDER BY action的相关子查询


提示:对于较大的集合,如果您使用索引临时表而不是CTE,这可能会更快。

谢谢@Shnugo的帮助

在您的帮助下,以下脚本为我提供了在我的数据集上工作所需的内容:

declare @id int
declare @maxid int

set @id = 1
select @maxid = max(idJCMaster) from _btblJCMaster

declare @IDseq table    (id int)

while @id < @maxid --whatever you max is
begin
    insert into @IDseq values(@id)

    set @id = @id + 1
end

;with source (id,dStartDate)
as
(
select 
    s.id
,   dStartDate
from        @IDseq s 
left join   _btblJCMaster t1 on s.id = t1.idJCMaster
)
, cte AS(SELECT id,dStartDate FROM source WHERE dStartDate IS NOT NULL)
SELECT t.id 
      ,A.gaplessStartDate
FROM source t
CROSS APPLY(SELECT TOP 1 cte.dStartDate 
            FROM cte 
            WHERE cte.id<=t.id 
            ORDER BY cte.id DESC) A(gaplessStartDate)
WHERE t.dStartDate IS NULL
order by id

如果您需要,这只供其他观众使用。

谢谢您,Ankit,我运行了它并收到以下消息:“LAG”函数必须有一个带有ORDER BY的OVER子句。然后我像这样添加了order:ISNULLdStartDate,LAGdStartDate-OVERorder-by-s.id,它现在工作了。然而,一些记录仍然显示为空,因为一次丢失3条以上的记录。。。不管怎么说,关于这个?哦。我忘了那个卡尔斯。让我也纠正一下。@Birel,请现在再试。Ankit,尝试过你正在编辑-没有成功,请参阅我对我的问题所做的编辑…@AnkitBajpai如果你仔细查看样本数据,你会发现ID在不断增加,但日期不是。使用MAXdStartdate不会产生所需的结果…谢谢@Shnugo!关于这一点,最好是提供一个自运行的独立样本,包括DDL、INSERT和您自己的尝试,我下次一定会提供:-这个脚本工作起来很有魅力,但是,我可以请求更改以仅显示空id,这样,您只能看到那些不存在的id的日期吗?如果你知道我的意思的话?@Birel如果我理解正确,那么添加t.dstardate为NULL的地方作为最后一行就足够了。
SELECT id, (SELECT MAX(dStartDate)
            FROM YOUR_TABLE
            WHERE id >= t1.id) dStartDate
FROM YOUR_TABLE t1;
DECLARE @tbl TABLE(id INT,  dStartDate DATE);
INSERT INTO @tbl VALUES
 (126,'2010-04-22 00:00:00.000')
,(127,NULL)
,(128,'2010-04-29 00:00:00.000')
,(129,'2010-05-03 00:00:00.000')
,(130,NULL)
,(131,NULL)
,(132,NULL)
,(133,'2010-04-29 00:00:00.000')
,(134,NULL)
,(135,NULL)
,(136,'2010-04-29 00:00:00.000')
,(137,NULL)
,(138,NULL)
,(139,'2010-04-29 00:00:00.000')
,(140,NULL)
,(141,'2010-04-29 00:00:00.000')
,(142,'2010-04-29 00:00:00.000')
,(143,NULL)
,(144,NULL);
WITH cte AS(SELECT id,dStartDate FROM @tbl WHERE dStartDate IS NOT NULL)
SELECT t.id 
      ,A.gaplessStartDate
FROM @tbl t
CROSS APPLY(SELECT TOP 1 cte.dStartDate 
            FROM cte 
            WHERE cte.id<=t.id 
            ORDER BY cte.id DESC) A(gaplessStartDate);
declare @id int
declare @maxid int

set @id = 1
select @maxid = max(idJCMaster) from _btblJCMaster

declare @IDseq table    (id int)

while @id < @maxid --whatever you max is
begin
    insert into @IDseq values(@id)

    set @id = @id + 1
end

;with source (id,dStartDate)
as
(
select 
    s.id
,   dStartDate
from        @IDseq s 
left join   _btblJCMaster t1 on s.id = t1.idJCMaster
)
, cte AS(SELECT id,dStartDate FROM source WHERE dStartDate IS NOT NULL)
SELECT t.id 
      ,A.gaplessStartDate
FROM source t
CROSS APPLY(SELECT TOP 1 cte.dStartDate 
            FROM cte 
            WHERE cte.id<=t.id 
            ORDER BY cte.id DESC) A(gaplessStartDate)
WHERE t.dStartDate IS NULL
order by id