web-dev-qa-db-fra.com

Comment cette table dérivée avec croix s'applique-t-elle?

J'ai emprunté un code sur la manière de compacter et de procéder à une chaîne de codes de diagnostic afin de créer une table de pont pour mon entrepôt de données. Ça marche bien. Cependant, je ne comprends tout simplement pas comment il fait la procédure de procédure. Voici le SQL Fiddle pour le code ci-dessous

create table dimDiagnosisGroup (dxGroupKey int, dxCodeList nvarchar(1024))
insert into dimDiagnosisGroup
values  (1,'042, 070.70, 722.10'),
        (2,'042, 070.70, 780.52, 496, 716.90, 581.9'),
        (3,'042, 070.70, 782.1, V58.69'),
        (4,'042, 070.70, 782.3, V58.69')


 WITH XMLTaggedList AS (
     SELECT dxGroupKey,
        CAST('<I>' + REPLACE(dxCodeList, ', ', '</I><I>') + '</I>' AS XML)
            AS Diagnosis_Code_List
     FROM dimDiagnosisGroup
 )
     SELECT dxGroupKey,
            ExtractedDiagnosisList.X.value('.', 'VARCHAR(MAX)') AS dxCodeList2
          FROM XMLTaggedList
        CROSS APPLY Diagnosis_Code_List.nodes('//I') AS ExtractedDiagnosisList(X)

Je comprends le Xmltaggedlist Partie parfaite. Ce que je ne comprends pas, c'est la croix s'applique à la extraitDiagnosislist (x) , alors le extrayédiagnosislist.x.value ('.', 'Varchar (max)') .

Lorsque je survole sur extraitDiagnostlist Dans l'instruction SELECT, SSMS dit qu'il s'agit d'une table dérivée. Cependant, cela ressemble à une fonction pour moi. Je ne comprends pas comment diagnostic_code.list obtient la fonction .Nodes ('// i'). Enfin, le extraitDiagnostlist.x.value semble étrangèrement à moi, en SQL. Cela ressemble à la syntaxe d'une langue comme c #.

6
Anthony Genovese

Ce que vous voyez est la mise en œuvre XQuery dans SQL Server. Bien que XQuery utilise son propre analyseur et effectue sa propre algébarisation au cours de la phase de compilation de la requête, les résultats sont combinés et optimisés avec la partie DML de la requête, puis combinées en un seul plan d'exécution.

SQL Server prend en charge cinq méthodes différentes. valeur , existe , , et Les nœuds sont utilisés pour accéder et transformer les données. Dernier, Modifier , utilise XML DML pour modifier les données.

La méthode Value () renvoie une valeur scalaire de l'instance XML permet de dire que vous avez le XML: `

declare @X xml =
'<Order OrderId="42" OrderTotal="49.96">
<Customer Id="123"/>
<OrderLineItems>
<OrderLineItem>
<ArticleId>250</ArticleId>
<Quantity>3</Quantity>
<Price>9.99</Price>
</OrderLineItem>
</OrderLineItems>
</Order>’

select @X.value('/Order[1]/Customer[1]/@Id','int')`or
select @X.value('(/Order/Customer/@Id)[1]','int')

Vous donnerait l'identifiant du premier client de la première commande

Dans votre valeur de cas particulière ('.') Signifie que toutes les valeurs de l'élément déchiqueté (que je parlerai d'un instant) N'oubliez pas d'utiliser la fonction de valeur que vous déplacez via XML. Maintenant, pour le rendre plus facile, de ne pas "déplacer" trop plus facile, vous pouvez utiliser la fonction nœud qui déchique-t-elle xml données relationnelles. Il renvoie une ligne définie avec des lignes représentant les nœuds identifiés par l'expression du chemin.

Exemple:

declare @X xml =
'<Order OrderId="42" OrderTotal="49.96">
<Customer Id="123"/>
<OrderLineItems>
<OrderLineItem>
<ArticleId>250</ArticleId>
<Quantity>3</Quantity>
<Price>9.99</Price>
</OrderLineItem>
</OrderLineItems>
</Order>'


select C.t.value('(@Id)[1]','int')
from  @X.nodes('/Order/Customer') as C(t)

Lorsque vous utilisez la méthode Nœuds () avec la colonne XML dans la table, vous devez utiliser l'opérateur Appliquer.

Exemple:

declare @X as table (xmlCode varchar(1000))
insert into @X values (
'<Order OrderId="42" OrderTotal="49.96">
<Customer Id="123"/>
<OrderLineItems>
<OrderLineItem>
<ArticleId>250</ArticleId>
<Quantity>3</Quantity>
<Price>9.99</Price>
</OrderLineItem>
</OrderLineItems>
</Order>');

WITH CTE AS(
select CAST(xmlCode as XML) as X from @X
)
select C.t.value('(@Id)[1]','int')
from  CTE
CROSS APPLY X.nodes('/Order/Customer') as C(t)

J'ai utilisé des exemples sur la valeur et le nœud, car vous avez fourni le code avec ces deux fonctions uniquement, si vous souhaitez en savoir plus à ce sujet, veuillez visiter Ceci

J'espère que ces simples exemples vous donnent une idée de la façon de demander des types XML

7
S4V1N

La croix s'applique est utilisée conjointement avec le .nodes() xquery appel. Ceci est essentiellement obtenir chaque élément <I></I> Pour les tableaux XML construits dans la déclaration XMLTaggedList CTE. L'appel externe .value() L'appel XQuery extrait ensuite cette valeur et le jette à un VARCHAR(MAX), renvoyant un enregistrement pour chaque code dans chaque groupe.

Je trouve plus facile de digérer si je brise la requête. Peut-être que vous irez aussi.

DECLARE @dimDiagnosisGroup TABLE (dxGroupKey int, dxCodeList nvarchar(1024))
insert into @dimDiagnosisGroup
values  (1,'042, 070.70, 722.10'),
        (2,'042, 070.70, 780.52, 496, 716.90, 581.9'),
        (3,'042, 070.70, 782.1, V58.69'),
        (4,'042, 070.70, 782.3, V58.69')

-- Construct the XML arrays, this is what's going on within the CTE
SELECT dxGroupKey,
CAST('<I>' + REPLACE(dxCodeList, ', ', '</I><I>') + '</I>' AS XML)
    AS Diagnosis_Code_List
FROM @dimDiagnosisGroup

-- Extract all elements for each group
 ;WITH XMLTaggedList AS (
     SELECT dxGroupKey,
        CAST('<I>' + REPLACE(dxCodeList, ', ', '</I><I>') + '</I>' AS XML)
            AS Diagnosis_Code_List
     FROM @dimDiagnosisGroup
 )
     SELECT dxGroupKey,
            -- Extract the Value from the <I></I> element and cast it as a VARCHAR(MAX)
            ExtractedDiagnosisList.X.value('.', 'VARCHAR(MAX)') AS dxCodeList2
          FROM XMLTaggedList
        -- Seperate each <I></I> element into it's own row
        CROSS APPLY Diagnosis_Code_List.nodes('//I') AS ExtractedDiagnosisList(X)
3
John Eisbrener

Un addenda à Réponse de John Eisbrener :

En ce qui concerne la partie ExtractedDiagnosisList(X) une partie, cela pourrait aider certains d'entre nous s'il y a une place dedans:

ExtractedDiagnosisList (X)

Du SQL DOCS , Tableaux dérivés (fonctionnalités de RowSet et @Variable. Function_Calls) vous permettent de spécifier non seulement un alias de table, mais une liste des alias de colonne pour les colonnes renvoyées dans la "Table" Dans la question. Dans ce cas, il y a une colonne, et nous allons appeler cela X.

Voir?

[De {} [ ... n]]
[.____] :: =
[.____] {

...

| rowet_function [[comme] table_alias]
[(bulk_column_alias [ ... n])]

...

| dérived_table [[comme] table_alias] [(colonne_alias [ ... n])]

...

| @ variable.function_call (expression [ ... n])
[[comme] table_alias] [(colonne_alias [ ... n])]

...

2
RDFozz