il y a quelques minutes j'ai demandé here comment obtenir des enregistrements parent avec un CTE récursif. Cela fonctionne maintenant, mais je reçois le mauvais ordre (en arrière, ordonné par le PK idData) quand je crée une fonction Table valorisée qui retourne tous les parents. Je ne peux pas commander directement parce que j'ai besoin de l'ordre logique fourni par le CTE.Mauvais ordre dans la fonction Table value (garder "l'ordre" d'un CTE récursif)
Cela donne l'ordre (de parent à côté de ce parent, etc.):
declare @fiData int;
set @fiData=16177344;
WITH PreviousClaims(idData,fiData)
AS(
SELECT parent.idData,parent.fiData
FROM tabData parent
WHERE parent.idData = @fiData
UNION ALL
SELECT child.idData,child.fiData
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
select iddata from PreviousClaims
Mais la retourne fonction suivante tous les enregistrements en ordre inversé (ordonnée par PK):
CREATE FUNCTION [dbo].[_previousClaimsByFiData] (
@fiData INT
)
RETURNS @retPreviousClaims TABLE
(
idData int PRIMARY KEY NOT NULL
)
AS
BEGIN
DECLARE @idData int;
WITH PreviousClaims(idData,fiData)
AS(
SELECT parent.idData,parent.fiData
FROM tabData parent
WHERE parent.idData = @fiData
UNION ALL
SELECT child.idData,child.fiData
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
INSERT INTO @retPreviousClaims
SELECT idData FROM PreviousClaims;
RETURN;
END;
select * from dbo._previousClaimsByFiData(16177344);
MISE à JOUR: Depuis les croyances de tout le monde que le CTE ne commande pas (Toute « commande "sera totalement arbitraire et coïncident), je me demande pourquoi le contraire semble être vrai. J'ai interrogé une demande d'enfant avec de nombreux parents et l'ordre dans le CTE est exactement l'ordre logique quand je vais de l'enfant à parent et ainsi de suite. Cela signifierait que le CTE itère d'un enregistrement à l'autre comme un curseur et que le select suivant le retourne exactement dans cet ordre. Mais quand j'appelle le TVF j'ai reçu l'ordre de la clé primaire idData à la place.
La solution était simple. J'ai seulement besoin d'enlever la clé parentale de la table de retour du TVF. Alors ... changer
RETURNS @retPreviousClaims TABLE
(
idData int PRIMARY KEY NOT NULL
)
à ...
RETURNS @retPreviousClaims TABLE
(
idData int
)
.. et il conserve le droit "ordre" (même ordre dans lequel ils ont été insérées dans le jeu temporaire de résultat du CTE).
MAJ2: Parce que Damien a mentionné que le « CTE ordre » pourrait changer dans certaines circonstances, je vais ajouter une nouvelle colonne relationLevel
au CTE qui décrit le niveau de la relation des enregistrements parents (ce qui est par la très utile en général pour un cube ssas). Ainsi, le Inline-TVF (qui renvoie toutes les colonnes) finale est maintenant:
CREATE FUNCTION [dbo].[_previousClaimsByFiData] (
@fiData INT
)
RETURNS TABLE AS
RETURN(
WITH PreviousClaims
AS(
SELECT 1 AS relationLevel, child.*
FROM tabData child
WHERE child.idData = @fiData
UNION ALL
SELECT relationLevel+1, child.*
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
SELECT TOP 100 PERCENT * FROM PreviousClaims order by relationLevel
)
C'est une relation exemplaire:
select idData,fiData,relationLevel from dbo._previousClaimsByFiData(46600314);
Merci.
La solution que vous avez publiée * peut fonctionner pour vous, maintenant, sur le serveur, le service pack et la base de données d'aujourd'hui. Mais ce n'est en aucun cas garanti. La seule façon de garantir l'ordre d'un ensemble de résultats consiste à spécifier une clause ORDER BY dans l'instruction SELECT la plus externe. –
Oui, cela semble mieux - cette sortie finale dépend toujours d'un détail d'implémentation (que "ORDER BY" dans INSERT est en relation avec l'ordre de récupération), mais au moins vous avez la colonne de tri disponible pour faire un ORDER BY sur cette sélection externe, si vous en avez besoin. –
Est-ce que ça fait une différence quand je définirais relationLevel comme clé primaire? Est-ce que l'ordre est garanti et n'a pas besoin d'être appliqué sur un select externe? –