Peguei emprestado algum código sobre como compactar e descompactar uma sequência de códigos de diagnóstico para construir uma tabela de ponte para meu data warehouse. Isso funciona bem. No entanto, eu simplesmente não entendo como ele está fazendo a descompactação. Aqui está o SQL Fiddle para o código abaixo
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)
Eu entendo bem a parte XMLTaggedList . O que não estou entendendo é o Cross Apply ao ExtractedDiagnosisList(X) , depois o ExtractedDiagnosisList.X.value('.', 'VARCHAR(MAX)') .
Quando passo o mouse sobre ExtractedDiagnosisList na instrução select, o SSMS diz que é uma tabela derivada. No entanto, parece uma função para mim. Não estou entendendo como Diagnosis_Code.List obtém a função .nodes('//I'). Finalmente, a seção ExtractedDiagnosisList.X.value parece estranha para mim, em SQL. Parece sintaxe de uma linguagem como C#.
O que você está vendo é a implementação do XQuery no SQL Server. Embora o XQuery use seu próprio analisador e execute sua própria algebrização durante o estágio de compilação da consulta, os resultados são combinados e otimizados junto com a parte DML da consulta e, em seguida, combinados em um único plano de execução.
O SQL Server oferece suporte a cinco métodos diferentes. value , exist , query e nodes são usados para acessar e transformar os dados. O último, modifique , usa XML DML para modificar os dados.
O método value() retorna um valor escalar da instância XML Digamos que você tenha o xml : `
Daria a você o ID do primeiro cliente do primeiro pedido
No seu caso particular value('.') significa dar-me todos os valores do elemento fragmentado (sobre o qual falarei em breve). Agora, para tornar mais fácil, não 'mover' muito, você pode usar o nó de função que fragmenta o XML em dados relacionais. Ele retorna um conjunto de linhas com linhas representando os nós identificados pela expressão de caminho.
Exemplo:
Ao usar o método nodes() com a coluna XML da tabela, você deve usar o operador APPLY.
Exemplo:
Eu usei exemplos sobre valor e nó, porque você forneceu o código apenas com essas duas funções, se você quiser ler mais sobre isso, visite este
Espero que estes exemplos simples lhe dêem uma ideia de como consultar tipos xml
O Cross Apply está sendo usado em conjunto com a
.nodes()
chamada XQuery. Isso basicamente está obtendo todos os elementos<I></I>
para os arrays XML construídos naXMLTaggedList
instrução CTE. A chamada externa.value()
de XQuery então extrai esse valor e o converte em umVARCHAR(MAX)
, retornando um registro para cada código dentro de cada grupo.Acho mais fácil digerir se eu quebrar a consulta. Talvez você também.
Um adendo à resposta de John Eisbrener :
Quanto à
ExtractedDiagnosisList(X)
peça, pode ajudar alguns de nós se houver um espaço nela:A partir dos documentos SQL , tabelas derivadas (e funções de conjunto de linhas e @variable. function_calls) permitem que você especifique não apenas um alias de tabela, mas uma lista de aliases de coluna para as colunas retornadas na "tabela" em questão. Neste caso, há uma coluna, e vamos chamá-la de
X
.Ver?
...
...
...
...