此时,我有一个包含列ID, Location, PartOfID
的表tblLocation
。
该表递归地连接到自身:PartOfID -> ID
我的目标是有一个选择输出如下:
> France > Paris > AnyCity >
说明:AnyCity位于巴黎,Paris位于法国。
到目前为止,我发现的解决方案是:
; 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运算符组合的查询的目标列表中的表达式数必须相等。
如果你知道我如何修复我的输出,那就太好了。
问题在于:
--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
为了使用union
或union all
,所有结果集的列数及其类型应相同。
我想您应该将列LOC_deelVan_LOC_id
添加到第二个结果集
然后,并集的两个部分之间的列数必须匹配。
为了构建完整路径,您需要"聚合"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;
第二个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
虽然这是一篇老文章,但我正在分享另一个工作示例。
";当使用"UNION"或"UNION ALL"时,列计数以及每个列数据类型必须匹配
让我们举一个例子:
1:
在SQL中,如果我们编写-SELECT"column1","column2"(注意:请记住用引号指定名称)在结果集中,它将显示带有两个标题的空列-列1和列2
2:我分享了我遇到的一个简单的例子
我在SQL中有七个列,其中包含一些不同的数据类型。即uniqueidentifier、datetime、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
上面的"inspectiond"one_answers"列documenttype"具有uniqueidentifer
数据类型,因此应用了CONVERT(NVARCHAR(36))
。列"modifiedon"是日期时间,因此应用了CONVERT(NVARCHAR(23), 'modifiedon', 126)
。
与上述第二个SELECT
查询并行,根据每列的数据类型匹配第一个SELECT
查询。
您可以使用递归标量函数:-
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 >