选择最大值小于值列表的条目
Selecting entries with biggest value less than list of values
假设我的table结构如下:
id | Word
---|-----
1 | a
2 | aa
. | ..
我有一个这样的 ID 列表:
(...,900, 1000, 2000, 3000, 4000,....)
我想找出比上面列表中每个id都小的最大id。
我的 table id 不一定是连续的,两个连续的 id 之间有一些间隔,例如:
(...,889,900,950,952,997,1000,1001,1010,1920,2000,2990,3000,3500,4000,...)
根据上述列表的预期结果为:
(889, 997, 1920, 2990, 3500,...)
我怎样才能达到预期的效果?
使用 common table expression and ROW_NUMBER()
;WITH cte AS(
SELECT *, ROW_NUMBER() OVER (ORDER BY ID) rowNum
FROM example)
SELECT ID, word
FROM cte
WHERE rowNum IN (
SELECT (rowNum - 1)
FROM cte
WHERE ID IN ('900','1000','2000','3000','4000'))
--WHERE ID IN (SELECT ID FROM <tableWithIDs>))
如果您已经在另一个 table 中找到了您正在寻找的所有 ID
,您可以使用我的答案的注释部分而不是硬编码的 IN
列表。
仅当您要查找的 ID
存在于 table 中时,此方法才有效。因此,正如下面的评论所述,如果您正在搜索 1001
,您将不会得到 997
,除非 1001
存在于 table 中(意思是,如果它存在,它将得到一个 rowNum
值并可用于在子查询中递减)
以下是另一种查看每行前一个 ID
的方法:
SELECT *, LEAD(ID,1) OVER(ORDER BY ID DESC) PreviousID
FROM example
ORDER BY ID
我会简单地做:
select v.val, t.*
from (values (900), (1000), (2000), (3000), (4000) ) v(val) outer apply
(select top 1 t.*
from t
where t.id < v.val
order by t.id desc
) t;
这样您就可以看到每一行的值。这可能很重要,因为 SQL 结果集是 无序的 并且哪个值对应哪一行并不明显。
编辑:
如果您知道行号在 table 中,最有效的解决方案可能是:
select t.*
from (select t.*, lead(id) over (order by id) as next_id
from t
) t
where next_id in ( . . . );
这应该可行,我认为它会相当有效。
declare @V table (num int primary key);
insert into @V values (800), (889), (900), (997), (1000), (1910), (1920), (2000), (2990), (3000), (3500), (4000);
declare @T table (num int primary key);
insert into @T values (800), (900), (1000), (1200), (2000), (3000), (4000);
select tt.vP
from ( select t.num as t, v.num as v
, LAG(v.num) over (order by v.num) as vP
from @V v
left join @T t
on v.num = t.num
) tt
where tt.t is not null
and tt.vP is not null
order by tt.vP
不清楚您希望它如何表现
select t.num
, (select max(v.num) from @V v where v.num < t.num) as prior
from @T t
假设我的table结构如下:
id | Word
---|-----
1 | a
2 | aa
. | ..
我有一个这样的 ID 列表:
(...,900, 1000, 2000, 3000, 4000,....)
我想找出比上面列表中每个id都小的最大id。 我的 table id 不一定是连续的,两个连续的 id 之间有一些间隔,例如:
(...,889,900,950,952,997,1000,1001,1010,1920,2000,2990,3000,3500,4000,...)
根据上述列表的预期结果为:
(889, 997, 1920, 2990, 3500,...)
我怎样才能达到预期的效果?
使用 common table expression and ROW_NUMBER()
;WITH cte AS(
SELECT *, ROW_NUMBER() OVER (ORDER BY ID) rowNum
FROM example)
SELECT ID, word
FROM cte
WHERE rowNum IN (
SELECT (rowNum - 1)
FROM cte
WHERE ID IN ('900','1000','2000','3000','4000'))
--WHERE ID IN (SELECT ID FROM <tableWithIDs>))
如果您已经在另一个 table 中找到了您正在寻找的所有 ID
,您可以使用我的答案的注释部分而不是硬编码的 IN
列表。
仅当您要查找的 ID
存在于 table 中时,此方法才有效。因此,正如下面的评论所述,如果您正在搜索 1001
,您将不会得到 997
,除非 1001
存在于 table 中(意思是,如果它存在,它将得到一个 rowNum
值并可用于在子查询中递减)
以下是另一种查看每行前一个 ID
的方法:
SELECT *, LEAD(ID,1) OVER(ORDER BY ID DESC) PreviousID
FROM example
ORDER BY ID
我会简单地做:
select v.val, t.*
from (values (900), (1000), (2000), (3000), (4000) ) v(val) outer apply
(select top 1 t.*
from t
where t.id < v.val
order by t.id desc
) t;
这样您就可以看到每一行的值。这可能很重要,因为 SQL 结果集是 无序的 并且哪个值对应哪一行并不明显。
编辑:
如果您知道行号在 table 中,最有效的解决方案可能是:
select t.*
from (select t.*, lead(id) over (order by id) as next_id
from t
) t
where next_id in ( . . . );
这应该可行,我认为它会相当有效。
declare @V table (num int primary key);
insert into @V values (800), (889), (900), (997), (1000), (1910), (1920), (2000), (2990), (3000), (3500), (4000);
declare @T table (num int primary key);
insert into @T values (800), (900), (1000), (1200), (2000), (3000), (4000);
select tt.vP
from ( select t.num as t, v.num as v
, LAG(v.num) over (order by v.num) as vP
from @V v
left join @T t
on v.num = t.num
) tt
where tt.t is not null
and tt.vP is not null
order by tt.vP
不清楚您希望它如何表现
select t.num
, (select max(v.num) from @V v where v.num < t.num) as prior
from @T t