错误 - 使用CTE进行递归选择时,“UNION运算符必须具有相同数量的表达式”

时间:2013-11-30 10:59:03

标签: sql sql-server tsql recursive-query

此时我有一个表tblLocation,其中包含ID, Location, PartOfID列。

该表以递归方式连接到自身:PartOfID -> ID

我的目标是选择一个输出:

> France > Paris > AnyCity >

说明:AnyCity位于巴黎,巴黎位于法国。

我到目前为止找到的解决方案是:

; with q as (
select ID,Location,PartOf_LOC_id from tblLocatie t
where t.ID = 1 -- 1 represents an example
union all
select t.Location + '>' from tblLocation t
inner join q parent on parent.ID = t.LOC_PartOf_ID
)
select * from q

不幸的是我收到以下错误:

  

使用UNION,INTERSECT或EXCEPT运算符组合的所有查询在其目标列表中必须具有相同数量的表达式。

如果您知道如何修复输出,那就太棒了。

5 个答案:

答案 0 :(得分:18)

问题出现在这里:

--This result set has 3 columns
select LOC_id,LOC_locatie,LOC_deelVan_LOC_id from tblLocatie t
where t.LOC_id = 1 -- 1 represents an example

union all

--This result set has 1 columns   
select t.LOC_locatie + '>' from tblLocatie t
inner join q parent on parent.LOC_id = t.LOC_deelVan_LOC_id

要使用unionunion all列数且其类型应与所有结果集相同。

我想您应该将列LOC_deelVan_LOC_id添加到第二个结果集

答案 1 :(得分:4)

第二个result set只有一列,但它应该有3列,以便满足第一个result set

(使用UNION时,列必须匹配)

尝试将ID添加为第一列,PartOf_LOC_id添加到result set,这样就可以执行UNION

;
WITH    q AS ( SELECT   ID ,
                    Location ,
                    PartOf_LOC_id
           FROM     tblLocation t
           WHERE    t.ID = 1 -- 1 represents an example
           UNION ALL
           SELECT   t.ID ,
                    parent.Location + '>' + t.Location ,
                    t.PartOf_LOC_id
           FROM     tblLocation t
                    INNER JOIN q parent ON parent.ID = t.LOC_PartOf_ID
         )
SELECT  *
FROM    q

答案 2 :(得分:4)

然后,联合体的两个部分之间的列数必须匹配。

要构建完整路径,您需要“聚合”Location列的所有值。您仍然需要选择CTE中的id和其他列,以便能够正确连接。你只需在外部选择中选择它们就可以“摆脱”它们:

with q as 
(
   select ID, PartOf_LOC_id, Location, ' > ' + Location as path
   from tblLocation 
   where ID = 1 

   union all

   select child.ID, child.PartOf_LOC_id, Location, parent.path + ' > ' + child.Location 
   from tblLocation child
     join q parent on parent.ID = t.LOC_PartOf_ID
)
select path
from q;

答案 3 :(得分:1)

您可以使用递归标量函数: -

set nocount on

create table location (
    id int,
    name varchar(50),
    parent int
)
insert into location values
    (1,'france',null),
    (2,'paris',1),
    (3,'belleville',2),
    (4,'lyon',1),
    (5,'vaise',4),
    (6,'united kingdom',null),
    (7,'england',6),
    (8,'manchester',7),
    (9,'fallowfield',8),
    (10,'withington',8)
go
create function dbo.breadcrumb(@child int)
returns varchar(1024)
as begin
    declare @returnValue varchar(1024)=''
    declare @parent int
    select @returnValue+=' > '+name,@parent=parent
    from location
    where id=@child
    if @parent is not null
        set @returnValue=dbo.breadcrumb(@parent)+@returnValue
    return @returnValue
end
go

declare @location int=1
while @location<=10 begin
    print dbo.breadcrumb(@location)+' >'
    set @location+=1
end

生产: -

 > france >
 > france > paris >
 > france > paris > belleville >
 > france > lyon >
 > france > lyon > vaise >
 > united kingdom >
 > united kingdom > england >
 > united kingdom > england > manchester >
 > united kingdom > england > manchester > fallowfield >
 > united kingdom > england > manchester > withington >

答案 4 :(得分:1)

尽管这是一篇老文章,但我在分享另一个工作示例。

“必须在使用'UNION'或'UNION ALL'时匹配列数以及每个列数据类型”

让我们举个例子:

1:

在SQL中,如果我们写-SELECT'column1','column2' (注意:请记住在引号中指定名称) 在结果集中,它将显示带有两个标题的空列column1和column2

2:我分享一个遇到的简单实例。

在SQL中,我有七个列,其中包含几种不同的数据类型。即uniqueidentifier,日期时间,nvarchar

我的任务是使用列标题检索逗号分隔的结果集。因此,当我将数据导出到CSV时,我用逗号分隔了各行,其中第一行为标题,并具有各自的列名。

SELECT CONVERT(NVARCHAR(36), 'Event ID') + ', ' + 
'Last Name' + ', ' + 
'First Name' + ', ' + 
'Middle Name' + ', ' + 
CONVERT(NVARCHAR(36), 'Document Type') + ', ' + 
'Event Type' + ', ' + 
CONVERT(VARCHAR(23), 'Last Updated', 126)

UNION ALL

SELECT CONVERT(NVARCHAR(36), inspectionid) + ', ' + 
       individuallastname + ', ' + 
       individualfirstname + ', ' + 
       individualmiddlename + ', ' +
       CONVERT(NVARCHAR(36), documenttype) + ', ' + 
       'I' + ', ' +
       CONVERT(VARCHAR(23), modifiedon, 126)
FROM Inspection

上面,列'inspectionid'和'documenttype'具有uniqueidentifer数据类型,因此被应用CONVERT(NVARCHAR(36))。列'mo​​difiedon'是日期时间,因此应用CONVERT(NVARCHAR(23), 'modifiedon', 126)

与第二个SELECT查询并行的匹配项是根据每列的数据类型与第一个SELECT查询匹配的。