En ce moment, j'ai une table tblLocation
avec les colonnes ID, Location, PartOfID
.
La table est connectée de manière récursive à elle-même: PartOfID -> ID
Mon but est d'avoir une sortie sélectionnée comme suit:
> France > Paris > AnyCity >
Explication: AnyCity est situé à Paris, Paris est situé en France.
Ma solution que j'ai trouvée jusqu'à présent était la suivante:
; 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
Malheureusement, j'obtiens l'erreur suivante:
Toutes les requêtes combinées à l'aide d'un opérateur UNION, INTERSECT ou EXCEPT doivent avoir un nombre égal d'expressions dans leurs listes de cibles.
Si vous avez une idée de la façon dont je pourrais corriger ma sortie, ce serait génial.
Le problème réside ici:
--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
Pour utiliser union
ou union all
nombre de colonnes et leurs types doivent être identiques, traversez tous les ensembles de résultats.
Je suppose que vous devriez simplement ajouter la colonne LOC_deelVan_LOC_id
à votre deuxième jeu de résultats
Le second result set
n'a qu'une colonne, mais il devrait avoir 3 colonnes pour qu'il soit contenu dans le premier result set
(les colonnes doivent correspondre lorsque vous utilisez UNION
)
Essayez d’ajouter ID
en tant que première colonne et PartOf_LOC_id
à votre result set
afin de pouvoir effectuer la 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
Ensuite, le nombre de colonnes doit correspondre entre les deux parties de l'union.
Afin de construire le chemin complet, vous devez "agréger" toutes les valeurs de la colonne Location
. Vous devez toujours sélectionner l'id et les autres colonnes à l'intérieur du CTE pour pouvoir vous joindre correctement. Vous vous en débarrassez simplement en ne les sélectionnant pas dans la sélection externe:
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;
Bien que ce soit un ancien post, je partage un autre exemple de travail.
"LE COMPTE DE COLONNE AINSI QUE CHAQUE COLONNE DE DONNEES DE DONNEES DOIT ÊTRE CORRESPONDANT LORSQUE 'UNION' OR 'UNION ALL' IS UTILISE"
Prenons un exemple:
En SQL si nous écrivons - SELECT 'colonne1', 'colonne2' (NOTE: n'oubliez pas de spécifier les noms entre guillemets) Dans un jeu de résultats, des colonnes vides avec deux en-têtes seront affichées: colonne1 et colonne2.
J'ai eu sept colonnes avec peu de types de données différents en SQL. C'est à dire. identifiant unique, date/heure, nvarchar
Ma tâche était de récupérer un ensemble de résultats séparés par des virgules avec un en-tête de colonne. Ainsi, lorsque j'exporte les données au format CSV, j'ai des lignes séparées par des virgules avec la première ligne comme en-tête et des noms de colonne respectifs.
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
Ci-dessus, les colonnes 'inspectionid' & 'documenttype' ont le type de données uniqueidentifer
et sont donc appliquées à CONVERT(NVARCHAR(36))
. La colonne 'modifiedon' est datetime et a donc été appliquée CONVERT(NVARCHAR(23), 'modifiedon', 126)
.
La seconde requête SELECT
correspondante correspond à la première requête SELECT
selon le type de données de chaque colonne.
Vous pouvez utiliser une fonction scalaire récursive: -
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
produit: -
> 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 >