在两列范围之间选择值

Posted

技术标签:

【中文标题】在两列范围之间选择值【英文标题】:Select values between two columns range 【发布时间】:2016-11-03 12:29:57 【问题描述】:

我有一张这样的桌子:

i1   i2
----------
1    a
1    b
1    c
1    d
2    x
3    y
4    a
4    b
4    c

我想选择 1 c 和 4 a 之间的行。 结果应该是:

1 c
1 d 
2 x 
3 y 
4 a

我该怎么做?

【问题讨论】:

您使用的是哪个 RDBMS? Sql Server 2014 标准 SQL:where (i1, i2) >= (1, 'c') and (i1, i2) <= (4, 'a') 但我不知道 SQL Server 是否支持 @a_horse_with_no_name:很遗憾,没有。 无论你在做什么,你都做错了。 【参考方案1】:

我会这样做:

select t.*
from t
where (i1 > 1 or (i1 = 1 and i2 >= 'c')) and
      (i1 < 4 or (i1 = 4 and i2 <= 'a'));

【讨论】:

我认为这是不可能的。【参考方案2】:

如果您使用的数据库支持行号功能,那么一种选择是根据您指定的顺序(即先按i1 升序,然后按@987654322 升序,使用行号创建表的 CTE @ 秒)。

然后,使用两个子查询来识别1c4a 的行号。这些行号构成了您要选择的范围。

;WITH cte AS (
    SELECT ROW_NUMBER() OVER (ORDER BY i1, i2) AS RowNumber, i1, i2
    FROM yourTable
)

SELECT *
FROM cte t
WHERE t.RowNumber >= (SELECT RowNumber FROM cte WHERE i1=1 AND i2='c') AND
      t.RowNumber <= (SELECT RowNumber FROM cte WHERE i1=4 AND i2='a')

【讨论】:

因为单个 where 子句就足够了,这对于查询来说太过分了。 @GordonLinoff 在 Stack Overflow,我们希望确保我们的问题已经彻底解决。因此需要过度杀伤这个查询:-) ?如果您已经在使用一个 CTE,为什么不使用更多的 CTE 而不是子查询 @onedaywhen 假设我们计划只运行实际查询一次或几次,通过创建子查询 CTE 真的会大大提高性能吗? ?我想我的意思是从样式/可读性的角度来看,即当您可以将 CTE 用于子查询并且您已经使用 CTE在查询中,为什么不【参考方案3】:

不是那么漂亮的方法......但是

create procedure GetRangeBetween (@i11 int, @i12 char, @i21 int, @i22 char)
AS
BEGIN

if object_id ('tempdb..#Test') is not null drop table #Test

create table #Test (i1 int, i2 nvarchar(10), [Rank] int)

insert into #Test(i1,   i2)
values
(1,   'a'),  (1,    'b'), (1,    'c'),
(1,    'd'), (2,    'x'), (3,    'y'),
(4,    'a'), (4,    'b'), (4,    'c')

update #Test
    set Rank = src.[srcRank]
from #Test t
    join (select *, row_number() over (order by i1) [srcRank] from #Test) src 
        on t.i1 = src.i1 and t.i2 = src.i2

declare @Rank1 int = (select [Rank] from #Test where i1 = @i11 and i2 = @i12)
declare @Rank2 int = (select [Rank] from #Test where i1 = @i21 and i2 = @i22)

select i1, i2 from #Test
    where (i1 between @i11 and @i21) and ([Rank] between @Rank1 and @Rank2) 
END

然后你只需用 ... 执行它。

execute GetRangeBetween 1, 'c', 4, 'a'

【讨论】:

[Rank] between 3 and 7 来自哪里? 在嵌套选择内部...有 row_number() 为您提供外部选择的 [Rank] 列 是的,但我们不能确定 (1,'c') 是排名 3。我们需要在某个地方找到排名范围。 修复了它,根本不用担心排名,因为存储过程......将始终有效:) 努力+1 :) 但是额外的列,为每次调用的所有值重新计算,听起来有点矫枉过正。查看上面 Tim Biegeleisen 的答案,以更优雅地实现类似的想法。【参考方案4】:

当然不是最佳解决方案,但这个查询应该可以工作:

select i1, i2
from tbl
where (i1 > 1 and i1 < 4)
    or (i1 = 1 and i2 >='c')
    or (i1 = 4 and i2 <='a')

请注意,结果中包含 (1, c) 和 (4, a)。如果您不需要包含边框,请更改比较运算符。

【讨论】:

以上是关于在两列范围之间选择值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 python 在两列中扩展具有日期范围的数据框?

mysql - 今天在两列值之间

在两列上创建索引以检查日期是不是介于这两个列之间

什么是 django 查询来查找搜索日期在两列之间的记录不是?

SQLAlchemy如何检查值是否在两列中的值之间?

MySQL在不使用表列的情况下选择两列之间的范围日期