【问题标题】:Using SQL FOR XML PATH, how can I achieve the following formatted XML output?使用 SQL FOR XML PATH,如何实现以下格式化的 XML 输出?
【发布时间】:2015-03-26 03:34:08
【问题描述】:

这个项目的范围比这个问题要大得多。我接到了一个项目的任务,我不会用私密的细节让你厌烦。最终我需要做的是将数据从数据库中取出并转换为 XML,这样我就可以转换为 JSON 并创建一个简单的 Web 应用程序,它允许我以满足客户需求的方式解析和格式化数据。

我确信有更好的方法来做到这一点,但这是我已经确定的路径..

我有大约 46,000 条记录转储到临时表中。为了让您了解这些数据的结构,运行以下查询:

SELECT 
    TransactionID,
    OwnerID,  
    Date, 
    TransactionType,
    ChargeCode, 
    Description, 
    DebitAmount
FROM #OwnerHistoryTemp
WHERE OwnerID = '11111111'

返回这个:

TransactionID   OwnerID     Date        TransactionType ChargeCode  Description         DebitAmount
28727           11111111    2014-12-01  E               A1          APPLY CHARGES       210.00  
28728           11111111    2014-12-03  C               A1          DB11111111          210.00  
28729           11111111    2015-01-01  E               A1          APPLY CHARGES       183.37  

我在这里要做的是使用 SQL FOR XML PATH(对任何其他建议开放)来输出数据,如下所示:

<OwnerHistory>
    <OwnerID OwnerID="11111111">
        <Transactions>
            <TransactionID ID="28727">
                <Date>2014-12-01</Date>
                <TransactionType>E</TransactionType>
                <ChargeCode>A1</ChargeCode>
                <Description>APPLY CHARGES</Description>
                <DebitAmount>210.00</DebitAmount>
            </TransactionID>
            <TransactionID ID="28728">
                <Date>2014-12-03</Date>
                <TransactionType>C</TransactionType>
                <ChargeCode>A1</ChargeCode>
                <Description>DB11111111</Description>
                <DebitAmount>210.00</DebitAmount>
            </TransactionID>
            <TransactionID ID="28729">
                <Date>2015-1-01</Date>
                <TransactionType>E</TransactionType>
                <ChargeCode>A1</ChargeCode>
                <Description>APPLY CHARGES</Description>
                <DebitAmount>183.37</DebitAmount>
            </TransactionID>
        </Transactions>
    </OwnerID>
</OwnerHistory>

我的 Query 让我很接近,但不是 QUITE 那里。因为同一个 OwnerID 出现多次(每个 TransactionID 一次),所以运行以下查询:

SELECT 
    OwnerID AS "@OwnerID", 
    TransactionID AS "Transaction/@RecordID", 
    Date AS "Transaction/Date", 
    TransactionType AS "Transaction/TransactionType",
    ChargeCode AS "Transaction/ChargeCode", 
    Description AS "Transaction/Description", 
    DebitAmount AS "Transaction/DebitAmount"
FROM #OwnerHistoryTemp
WHERE OwnerID = '11111111'
GROUP BY OwnerID, RecordID, Date, ChargeCode, Description, DebitAmount
order by OwnerID
FOR XML PATH ('OwnerID'), ROOT('OwnerHistory')

返回以下内容:

<OwnerHistory>
    <OwnerID OwnerID="11111111">
        <Transaction RecordID="28727">
            <Date>2014-12-01</Date>
            <TransactionType>E</TransactionType>
            <ChargeCode>A1</ChargeCode>
            <Description>APPLY CHARGES</Description>
            <DebitAmount>210.0000</DebitAmount>
        </Transaction>
    </OwnerID>
    <OwnerID OwnerID="11111111">
        <Transaction RecordID="28728">
            <Date>2014-12-03</Date>
            <TransactionType>C</TransactionType>
            <ChargeCode>A1</ChargeCode>
            <Description>DB11111111</Description>
            <DebitAmount>210.0000</DebitAmount>
        </Transaction>
    </OwnerID>
    <OwnerID OwnerID="11111111">
        <Transaction RecordID="28729">
            <Date>2015-01-01</Date>
            <TransactionType>E</TransactionType>
            <ChargeCode>A1</ChargeCode>
            <Description>APPLY CHARGES</Description>
            <DebitAmount>183.3700</DebitAmount>
        </Transaction>
    </OwnerID>
</OwnerHistory>

关于如何仅将 OwnerID 作为 Parent 提取一次并将所有事务分组在其下的任何想法?

可能是一些我只是不理解的简单事情,或者这可能是不可能的。如果是前者,请随意公开鞭打我......

【问题讨论】:

    标签: sql sql-server sql-server-2012 for-xml for-xml-path


    【解决方案1】:

    准备好接受鞭刑了吗?

    嵌套查询以获得嵌套的 XML,如下所示:

    SELECT TOP 1
      OwnerID AS "@ID",
      (SELECT
          TransactionID AS "Transaction/@ID",
          [Date] AS "Transaction/Date",
          TransactionType AS "Transaction/Type",
          ChargeCode AS "Transaction/ChargeCode",
          [Description] AS "Transaction/Description",
          DebitAmount AS "Transaction/DebitAmount"
        FROM OwnerHistory
        WHERE OwnerID = [Owner].OwnerID
        FOR XML PATH(''), TYPE) Transactions
    FROM OwnerHistory [Owner]
    WHERE OwnerID = '11111111' 
    FOR XML PATH('Owner'), ROOT('OwnerHistory'), TYPE
    

    生成的 XML:

    <OwnerHistory>
      <Owner ID="11111111">
        <Transactions>
          <Transaction ID="28727">
            <Date>2015-03-26</Date>
            <Type>E</Type>
            <ChargeCode>A1</ChargeCode>
            <Description>APPLY CHARGES</Description>
            <DebitAmount>210.0000</DebitAmount>
          </Transaction>
          <Transaction ID="28728">
            <Date>2015-03-26</Date>
            <Type>C</Type>
            <ChargeCode>A1</ChargeCode>
            <Description>DB11111111</Description>
            <DebitAmount>210.0000</DebitAmount>
          </Transaction>
          <Transaction ID="28729">
            <Date>2015-03-26</Date>
            <Type>E</Type>
            <ChargeCode>A1</ChargeCode>
            <Description>APPLY CHARGES</Description>
            <DebitAmount>183.3700</DebitAmount>
          </Transaction>
        </Transactions>
      </Owner>
    </OwnerHistory>
    

    请注意,包含TOP 1 只是为了避免对包含OwnerID 的每一行重复整个事务集。这可以通过多种方式处理;通常这种嵌套是两个规范化表连接的结果,因此只会出现Owner 的一个实例。

    MSDN 有一些很好的 examples 来演示这种技术。

    【讨论】:

    • Hmmmmmm .....我试过运行它并稍微调整一下。我也阅读了文档。我会继续玩它,看看我能想出什么。感谢您的回复!
    • @FernandoVega,对此感到抱歉,我在没有使用数据库的情况下通过手机接听电话。我已经用经过测试的查询更新了答案。
    • 嘿伙计!!这太妙了!!我是如此接近,但到目前为止:'(我真的很感谢你花时间研究这个并为我解决这个问题。不仅如此,而且教育我!我不确定你在哪里,但如果你曾经在明尼苏达州,您至少有 12 包啤酒等着您!见鬼,一整箱!仅供参考,我试图支持您的解决方案,但它不会让我每没有 15 的声誉等级。如果/当我这样做时,我会尝试回来给你一些积分!!再次感谢!!!
    • @FernandoVega 很高兴我能帮上忙。我过去两年编写的系统很大程度上依赖于从 SQL Server 构建 XML,所以我知道这个概念,但如果不实际操作,我就无法完全理解语法。
    猜你喜欢
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多