在SQL中将值列表与表行联接

在SQL中将值列表与表行联接,sql,sql-server,oracle,Sql,Sql Server,Oracle,假设我有一个值列表,例如1、2、3、4、5和一个表,其中一些值存在于某个列中。以下是一个例子: id name 1 Alice 3 Cindy 5 Elmore 6 Felix 我想创建一个SELECT语句,该语句将包含我列表中的所有值以及与这些值匹配的行中的信息,即,在我的列表和表之间执行左外部联接,因此结果如下所示: id name 1 Alice 2 (null) 3 Cindy 4 (null) 5 Elmore 如何在不创建临时表或不使用多个

假设我有一个值列表,例如1、2、3、4、5和一个表,其中一些值存在于某个列中。以下是一个例子:

id  name
 1  Alice
 3  Cindy
 5  Elmore
 6  Felix
我想创建一个SELECT语句,该语句将包含我列表中的所有值以及与这些值匹配的行中的信息,即,在我的列表和表之间执行左外部联接,因此结果如下所示:

id  name
 1  Alice
 2  (null)
 3  Cindy
 4  (null)
 5  Elmore

如何在不创建临时表或不使用多个联合运算符的情况下执行此操作?

如果在Microsoft SQL Server 2008或更高版本中,则可以使用


不知道Oracle是否有类似的结构

假设myTable是您的表名,下面的代码应该可以工作

;with x as 
(
  select top (select max(id) from [myTable]) number from [master]..spt_values
),
y as
(select row_number() over (order by x.number) as id
from x)
select y.id,  t.name
from y left join myTable as t
on y.id = t.id;
注意:这是SQL Server实现


以下针对oracle的解决方案采用自。其基本思想是利用oracle的分层查询。您必须在下面的示例查询中指定列表100的最大长度

   select d.lstid
        , t.name
     from (
               select substr(
                           csv
                         , instr(csv,',',1,lev) + 1
                         , instr(csv,',',1,lev+1 )-instr(csv,',',1,lev)-1
                      )  lstid
                 from (select ','||'1,2,3,4,5'||',' csv from dual)
                    , (select level lev from dual connect by level <= 100)
                where lev <= length(csv)-length(replace(csv,','))-1         
          ) d
left join test  t on ( d.lstid = t.id )
        ;

查看以查看其工作情况。

假设具有值1、2、3、4、5的表名为“值列表”,并且假设包含某些值但具有名称列作为某些值的表,您可以执行以下操作:

SELECT B.id,A.name
FROM [list_of_values] AS B
LEFT JOIN [some_values] AS A
ON B.ID = A.ID

这有点晚了,但对于Oracle,您可以这样做以获得一个值表:

SELECT rownum + 5 /*start*/ - 1 as myval
FROM dual
CONNECT BY LEVEL <= 100 /*end*/ - 5 /*start*/ + 1
。。。然后将其加入到您的表中:

SELECT *
FROM
(SELECT rownum + 1 /*start*/ - 1 myval
FROM dual
CONNECT BY LEVEL <= 5 /*end*/ - 1 /*start*/ + 1) mypseudotable
left outer join myothertable
    on mypseudotable.myval = myothertable.correspondingval

为了获得部分输出所需的序列号,此方法消除了为n个数字键入的值:

declare @site as int
set @site = 1
while @site<=200
begin
insert into ##table
values (@site)

set @site=@site+1
end

什么数据库产品?MS SQL Server或Oracle。我不确定我是否理解。值1,2,3,4,5的列表是如何起作用的,在哪里起作用的?这可以处理从1到你的最高id可能是1,2,3,4,5,…,的任何事情。我引入id列只是为了进行说明。值的列表不必表示id、rownum甚至序列号的列表。它可以由任意字符串或任何其他不同的值组成。问题是值列表不在任何表中。我想我最初的问题可以归结为:如何将任意值列表转换为可用于联接的子查询?这在各种情况下都非常有用。是否有一种方法可以动态生成一系列int而不是硬编码它们?在SQL Server中工作,但我仍在寻找一种更有用的命令格式,因为单个值周围的括号太多了。@user3079364,动态地说是什么意思?你是说在T-SQL中?如果是这样,那么请创建一个空表变量,然后使用使用您希望的任何逻辑生成的T-SQL Insert语句填充它。@JakeJ、括号或其他标记作为每行数据之间的分隔符是必需的。在每一个括号中,都会有一组逗号分隔的数据行值。。。如值1、16、‘Dave’、2、22、‘Mary’、3、8、‘joey’、4、55、‘Dad’、5、46、‘Mom’v人格、年龄、姓名。如果没有括号,则需要一些其他标记来分隔行。请修复问题的格式好吗?
declare @site as int
set @site = 1
while @site<=200
begin
insert into ##table
values (@site)

set @site=@site+1
end
select * from ##table
select v.id,m.name from  ##table  as v
left outer join [source_table] m
 on m.id=v.id