AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 177532
Accepted
Anthony Genovese
Anthony Genovese
Asked: 2017-06-29 10:44:39 +0800 CST2017-06-29 10:44:39 +0800 CST 2017-06-29 10:44:39 +0800 CST

这个带有交叉应用的派生表如何工作?

  • 772

我借用了一些关于如何压缩和解压缩诊断代码字符串的代码,以便为我的数据仓库构建一个桥接表。它运作良好。但是,我只是不明白它是如何进行压缩的。这是以下代码的 SQL Fiddle

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)

我理解XMLTaggedList部分很好。我不明白的是 Cross Apply 到ExtractedDiagnosisList(X),然后是ExtractedDiagnosisList.X.value('.', 'VARCHAR(MAX)')。

当我在 select 语句中将鼠标悬停在ExtractedDiagnosisList上时,SSMS 说它是一个派生表。但是,它对我来说有点像一个功能。我不明白Diagnosis_Code.List如何获取 .nodes('//I') 函数。最后,在 SQL 中, ExtractedDiagnosisList.X.value部分对我来说看起来很陌生。它看起来像 C# 等语言的语法。

sql-server functions
  • 3 3 个回答
  • 1796 Views

3 个回答

  • Voted
  1. Best Answer
    S4V1N
    2017-06-29T11:29:17+08:002017-06-29T11:29:17+08:00

    您看到的是 SQL Server 中的 XQuery 实现。尽管 XQuery 使用自己的解析器并在查询编译阶段执行自己的代数化,但结果会与查询的 DML 部分一起组合和优化,然后组合成一个执行计划。

    SQL Server 支持五种不同的方法。 value、exists、query和 nodes用于访问和转换数据。最后一个,modify,使用 XML DML 来修改数据。

    value() 方法从 XML 实例返回一个标量值假设您有 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')
    

    会给你第一个订单的第一个客户的 ID

    在您的特定情况下,value('.') 意味着给我来自切碎元素的所有值(我稍后会谈到)请记住,在使用值函数时,您正在通过 XML 移动。现在为了使它更容易,不要“移动”太多,您可以使用功能节点将 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 C.t.value('(@Id)[1]','int')
    from  @X.nodes('/Order/Customer') as C(t)
    

    当您对表中的 XML 列使用 nodes() 方法时,您必须使用 APPLY 运算符。

    例子:

    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)
    

    我在值和节点上使用了示例,因为您仅提供了具有这两个功能的代码,如果您想了解更多信息,请访问此

    希望这个简单的例子能让你了解如何查询 xml 类型

    • 7
  2. John Eisbrener
    2017-06-29T10:49:25+08:002017-06-29T10:49:25+08:00

    Cross Apply 与.nodes()XQuery 调用结合使用。这基本上是获取在CTE 语句中<I></I>构造的 XML 数组的每个元素。XMLTaggedList然后,外部.value()XQuery 调用提取该值并将其强制转换为 a VARCHAR(MAX),为每个组中的每个代码返回一条记录。

    如果我分解查询,我发现更容易消化。也许你也会。

    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
  3. RDFozz
    2017-06-29T11:08:39+08:002017-06-29T11:08:39+08:00

    John Eisbrener 回答的附录:

    就ExtractedDiagnosisList(X)部分而言,如果其中有空格,它可能会对我们中的一些人有所帮助:

    ExtractedDiagnosisList (X)
    

    从SQL 文档中,派生表(和行集函数,以及 @variable.function_calls)不仅允许您指定表别名,还允许您指定相关“表”中返回的列的列别名列表。在本例中,只有一列,我们将其命名为X。

    看?

    [ 来自 { } [ ,...n ] ]
    ::=
    {

    ...

    | rowset_function [ [ AS ] table_alias ]
    [ ( bulk_column_alias [ ,...n ] ) ]

    ...

    | 派生表 [ [ AS ] table_alias ] [ ( column_alias [ ,...n ] ) ]

    ...

    | @variable.function_call ( 表达式 [ ,...n ] )
    [ [ AS ] table_alias ] [ (column_alias [ ,...n ] ) ]

    ...

    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve