Oracle中有一个表格列:
id | start_number | end_number
---+--------------+------------
1 | 100 | 200
2 | 151 | 200
3 | 25 | 49
4 | 98 | 99
5 | 49 | 100
有一个数字列表(50,99,150)。
我想要一个sql语句,它返回所有id,其中找到数字列表中的任何数字等于或者在start_number和end_number之间。
使用上面的例子;应退回1,4和5
1 - 150介于或等于100和200之间
2 - 没有数字在151和200之间
3 - 没有数字在25和49之间
4 - 99介于或等于98和99
之间
5-50和99等于或等于49和100
drop table TEMP_TABLE;
create table TEMP_TABLE(
THE_ID number,
THE_START number,
THE_END number
);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (1, 100, 200);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (2, 151, 200);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (3, 25, 49);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (4, 98, 99);
insert into TEMP_TABLE(the_id, the_start, the_end) values (5, 49, 100);
以下是我根据以下评论和答案以及其他一些研究提出的解决方案:
SELECT
*
from
TEMP_TABLE
where
EXISTS (select * from(
select column_value as id
from table(SYS.DBMS_DEBUG_VC2COLL(50,99,150))
)
where id
BETWEEN TEMP_TABLE.the_start AND TEMP_TABLE.the_end
)
这也有效:
SELECT
*
from
TEMP_TABLE
where
EXISTS (select * from(
select column_value as id
from table(sys.ku$_vcnt(50,99,150))
)
where id
BETWEEN TEMP_TABLE.the_start AND TEMP_TABLE.the_end
)
答案 0 :(得分:3)
以下是一个完整的例子:
create table #list (
number int
)
create table #table (
id int,
start_number int,
end_number int
)
insert into #list values(50)
insert into #list values(99)
insert into #list values(150)
insert into #table values(1,100,200)
insert into #table values(2,151,200)
insert into #table values(3,25,49)
insert into #table values(4,98,99)
insert into #table values(5,49,100)
select distinct a.* from #table a
inner join #list l --your list of numbers
on l.number between a.start_number and a.end_number
drop table #list
drop table #table
您只需删除关于#table (create, insert and drop)
的代码,然后将table
放入select
。
答案 1 :(得分:2)
这在一定程度上取决于您存储数字列表的方式。我会假设他们现在在另一张桌子上,因为即便如此,你还有很多选择。
SELECT
*
FROM
yourTable
WHERE
EXISTS (SELECT * FROM yourList WHERE number BETWEEN yourTable.start_number AND yourTable.end_number)
或者...
SELECT
*
FROM
yourTable
INNER JOIN
yourList
ON yourList.number BETWEEN yourTable.start_number AND yourTable.end_number
这两个都是最简单的表达式,适用于小型数据集。但是,如果您的数字列表相对较小,而您的原始数据相对较大,则可能无法很好地扩展。这是因为上面两个都扫描了整个yourTable
,然后根据你的列表检查每个记录。
最好是扫描列表,然后尝试使用索引来检查原始数据。这将要求您能够将BETWEEN语句反转为yourTable.start_number BETWEEN x and y
只有在知道start_number和end_number之间的最大差距时才能这样做。
SELECT
*
FROM
yourList
INNER JOIN
yourTable
ON yourTable.end_number >= yourList.number
AND yourTable.start_number <= yourList.number
AND yourTable.start_number >= yourList.number - max_gap
为了达到这个目的,我将max_gap的值存储在另一个表中,并将其更新为yourTable中的值更改。
答案 2 :(得分:1)
如果数字不在一个中,您将需要创建一个临时表来保存您的号码。然后变得相对简单:
SELECT DISTINCT mt.ID FROM MyTable mt
INNER JOIN TempTable tt --your list of numbers
ON tt.number Between mt.start_number and mt.end_number
要基于传递值数组创建表,可以在过程中使用表定义。我对Oracle语法很清楚并且没有TOAD方便,但你应该能够得到这样的东西:
CREATE OR REPLACE PROCEDURE FindIdsFromList
AS
DECLARE
TYPE NumberRecord IS RECORD (Number int NOT NULL)
TYPE NumberList IS TABLE OF NumberRecord;
NumberList myNumberList;
BEGIN
myNumberList := (50,99,150);
SELECT DISTINCT mt.ID FROM MyTable mt
INNER JOIN myNumberList nt --your list of numbers
ON nt.Number Between mt.start_number and mt.end_number
END