【问题标题】:XML query on T-SQLT-SQL 上的 XML 查询
【发布时间】:2021-12-05 18:43:09
【问题描述】:

非常感谢您对以下内容的任何帮助。

下面是我的表结构:

CREATE TABLE [dbo].[XML_EXAMPLE]
(
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Account Code] [varchar](15) NULL,
    [Description] [varchar](50) NULL,
    [Analysis 1 Code] [varchar](15) NULL,
    [Analysis 2 Code] [varchar](15) NULL,
    [Analysis 3 Code] [varchar](15) NULL,
    [Analysis 4 Code] [varchar](15) NULL,
    [Analysis 5 Code] [varchar](15) NULL,
    [Analysis 6 Code] [varchar](15) NULL,
    [Analysis 7 Code] [varchar](15) NULL
) ON [PRIMARY]
GO

在该表中,我将插入 4 行。两行的分析 1 代码为 1000,另外两行的分析 1 代码为 2000。

INSERT INTO [dbo].[XML_EXAMPLE] ([Analysis 1 Code])
VALUES ('1000'), ('1000'), ('2000'), ('2000')

我试图从 SQL 中得到的是一种如下所示的 XML 格式 - 请注意,如果您查看 CompCode,每个 Analysis 1 Code 都有其自己的“文档”元素。每个 Document 元素都有一个 Header 和 Item(表中的行)。

<DocumentBatch>
  <Document>
    <Header>
      <DocType>HR</DocType>
      <CompCode>1000</CompCode>
      <DocDate>20211018</DocDate>
      <PostDate>20211018</PostDate>
      <RefDocNo>Civica Cx Rents</RefDocNo>
      <Text>Civica Cx Rents</Text>
    </Header>
    <Item>
      <ItemNo>1</ItemNo>
      <GIAccNo>GIAccNo</GIAccNo>
      <TaxCode>TaxCode</TaxCode>
      <Amount>Amount</Amount>
      <Currency>Currency</Currency>
      <Text>Text</Text>
      <CostCenter>CostCenter</CostCenter>
      <RefKey1>RefKey1</RefKey1>
      <RefKey2>RefKey2</RefKey2>
      <RefKey3>RefKey3</RefKey3>
    </Item>
    <Item>
      <ItemNo>2</ItemNo>
      <GIAccNo>GIAccNo</GIAccNo>
      <TaxCode>TaxCode</TaxCode>
      <Amount>Amount</Amount>
      <Currency>Currency</Currency>
      <Text>Text</Text>
      <CostCenter>CostCenter</CostCenter>
      <RefKey1>RefKey1</RefKey1>
      <RefKey2>RefKey2</RefKey2>
      <RefKey3>RefKey3</RefKey3>
    </Item>
  </Document>
<Document>
        <Header>
            <DocType>HR</DocType>
            <CompCode>2000</CompCode>
            <DocDate>20211018</DocDate>
            <PostDate>20211018</PostDate>
            <RefDocNo>Civica Cx Rents</RefDocNo>
            <Text>Civica Cx Rents</Text>
        </Header>
        <Item>
            <ItemNo>1</ItemNo>
            <GIAccNo>GIAccNo</GIAccNo>
            <TaxCode>TaxCode</TaxCode>
            <Amount>Amount</Amount>
            <Currency>Currency</Currency>
            <Text>Text</Text>
            <CostCenter>CostCenter</CostCenter>
            <RefKey1>RefKey1</RefKey1>
            <RefKey2>RefKey2</RefKey2>
            <RefKey3>RefKey3</RefKey3>
        </Item>
        <Item>
            <ItemNo>2</ItemNo>
            <GIAccNo>GIAccNo</GIAccNo>
            <TaxCode>TaxCode</TaxCode>
            <Amount>Amount</Amount>
            <Currency>Currency</Currency>
            <Text>Text</Text>
            <CostCenter>CostCenter</CostCenter>
            <RefKey1>RefKey1</RefKey1>
            <RefKey2>RefKey2</RefKey2>
            <RefKey3>RefKey3</RefKey3>
        </Item>
    </Document>
</DocumentBatch>

我编写的代码只处理其中一个分析 1 代码。如果你要运行这段代码 - 你会发现它只会给我想要的一半。

SELECT
    (SELECT 
         (SELECT DISTINCT 
              'HR' DocType, 
              x.[Analysis 1 Code] CompCode, 
              CONVERT(varchar(8), GETDATE(), 112) DocDate, 
              CONVERT(varchar(8), GETDATE(), 112) PostDate, 
              'Civica Cx Rents' RefDocNo, 
              'Civica Cx Rents' Text
          FROM 
              XML_EXAMPLE x
          WHERE 
              x.[Analysis 1 Code] = '1000'
          FOR XML path('Header'), TYPE),
         (SELECT  
              ROW_NUMBER() OVER (ORDER BY id) 'ItemNo',
              'GIAccNo' 'GIAccNo',
              'TaxCode' 'TaxCode',
              'Amount' 'Amount',
              'Currency' 'Currency',
              'Text' 'Text',
              'CostCenter' 'CostCenter',
              'RefKey1' 'RefKey1',
              'RefKey2' 'RefKey2',
              'RefKey3' 'RefKey3'
          FROM 
              XML_EXAMPLE x
          WHERE 
              x.[Analysis 1 Code] = '1000'
          FOR XML PATH('Item'), TYPE)
      FOR XML PATH('Document'), TYPE, ROOT ('DocumentBatch')) row

我的结果 - 请注意,我只有 1 个带有标题的 Document 元素和 1000 个项目。

<DocumentBatch>
  <Document>
    <Header>
      <DocType>HR</DocType>
      <CompCode>1000</CompCode>
      <DocDate>20211018</DocDate>
      <PostDate>20211018</PostDate>
      <RefDocNo>Civica Cx Rents</RefDocNo>
      <Text>Civica Cx Rents</Text>
    </Header>
    <Item>
      <ItemNo>1</ItemNo>
      <GIAccNo>GIAccNo</GIAccNo>
      <TaxCode>TaxCode</TaxCode>
      <Amount>Amount</Amount>
      <Currency>Currency</Currency>
      <Text>Text</Text>
      <CostCenter>CostCenter</CostCenter>
      <RefKey1>RefKey1</RefKey1>
      <RefKey2>RefKey2</RefKey2>
      <RefKey3>RefKey3</RefKey3>
    </Item>
    <Item>
      <ItemNo>2</ItemNo>
      <GIAccNo>GIAccNo</GIAccNo>
      <TaxCode>TaxCode</TaxCode>
      <Amount>Amount</Amount>
      <Currency>Currency</Currency>
      <Text>Text</Text>
      <CostCenter>CostCenter</CostCenter>
      <RefKey1>RefKey1</RefKey1>
      <RefKey2>RefKey2</RefKey2>
      <RefKey3>RefKey3</RefKey3>
    </Item>
  </Document>
</DocumentBatch>

我一辈子都做不到的是-

  1. 如何将&lt;?xml version="1.0" encoding="iso8859-1"?&gt; 附加到我生成的 XML 格式的顶部 - 因为我将通过 SSIS 包进行设置。

  2. 我在我的代码中放置在哪里,以便它最终导出 1000 和 2000,因为我正在努力将它放置在哪里。为了达到我想要的目的,我是否错误地构建了我的代码?

非常感谢

【问题讨论】:

    标签: sql-server xml tsql ssis


    【解决方案1】:

    请尝试以下解决方案。

    它正在使用 SQL Server 的 XQuery 及其 FLWOR 表达式。

    XML 组合分两步完成:

    1. 原始 XML 来自 FOR XML PATH(...)
    2. 通过 XQuery FLWOR 表达式最终微调 XML。

    SQL

    -- DDL and sample data population, start
    DECLARE @tbl TABLE
    (
        ID int IDENTITY PRIMARY KEY,
        Account_Code varchar(15) NULL,
        [Description] varchar(50) NULL,
        Analysis_1_Code varchar(15) NULL
    );
    INSERT INTO @tbl (Analysis_1_Code) VALUES 
    ('1000'), ('1000'), ('2000'), ('2000');
    -- DDL and sample data population, end
    
    SELECT (
        SELECT * 
        , seq = ROW_NUMBER() OVER (PARTITION BY Analysis_1_Code ORDER BY ID)
        FROM @tbl
        FOR XML PATH('r'), TYPE, ROOT('root'))
    .query('<DocumentBatch>
    {
    for $x in distinct-values(/root/r/Analysis_1_Code)
    return (<Document>
            <Header>
                <DocType>HR</DocType>
                <CompCode>{$x}</CompCode>
                <DocDate>20211018</DocDate>
                <PostDate>20211018</PostDate>
                <RefDocNo>Civica Cx Rents</RefDocNo>
                <Text>Civica Cx Rents</Text>
            </Header>
        </Document>,
        for $y in /root/r[Analysis_1_Code=$x]
        return <Item>
                <ItemNo>{data($y/seq)}</ItemNo>
                <GIAccNo>GIAccNo</GIAccNo>
                <TaxCode>TaxCode</TaxCode>
                <Amount>Amount</Amount>
                <Currency>Currency</Currency>
                <Text>Text</Text>
                <CostCenter>CostCenter</CostCenter>
                <RefKey1>RefKey1</RefKey1>
                <RefKey2>RefKey2</RefKey2>
                <RefKey3>RefKey3</RefKey3>
            </Item>)
    }
    </DocumentBatch>');
    

    输出

    <DocumentBatch>
      <Document>
        <Header>
          <DocType>HR</DocType>
          <CompCode>1000</CompCode>
          <DocDate>20211018</DocDate>
          <PostDate>20211018</PostDate>
          <RefDocNo>Civica Cx Rents</RefDocNo>
          <Text>Civica Cx Rents</Text>
        </Header>
      </Document>
      <Item>
        <ItemNo>1</ItemNo>
        <GIAccNo>GIAccNo</GIAccNo>
        <TaxCode>TaxCode</TaxCode>
        <Amount>Amount</Amount>
        <Currency>Currency</Currency>
        <Text>Text</Text>
        <CostCenter>CostCenter</CostCenter>
        <RefKey1>RefKey1</RefKey1>
        <RefKey2>RefKey2</RefKey2>
        <RefKey3>RefKey3</RefKey3>
      </Item>
      <Item>
        <ItemNo>2</ItemNo>
        <GIAccNo>GIAccNo</GIAccNo>
        <TaxCode>TaxCode</TaxCode>
        <Amount>Amount</Amount>
        <Currency>Currency</Currency>
        <Text>Text</Text>
        <CostCenter>CostCenter</CostCenter>
        <RefKey1>RefKey1</RefKey1>
        <RefKey2>RefKey2</RefKey2>
        <RefKey3>RefKey3</RefKey3>
      </Item>
      <Document>
        <Header>
          <DocType>HR</DocType>
          <CompCode>2000</CompCode>
          <DocDate>20211018</DocDate>
          <PostDate>20211018</PostDate>
          <RefDocNo>Civica Cx Rents</RefDocNo>
          <Text>Civica Cx Rents</Text>
        </Header>
      </Document>
      <Item>
        <ItemNo>1</ItemNo>
        <GIAccNo>GIAccNo</GIAccNo>
        <TaxCode>TaxCode</TaxCode>
        <Amount>Amount</Amount>
        <Currency>Currency</Currency>
        <Text>Text</Text>
        <CostCenter>CostCenter</CostCenter>
        <RefKey1>RefKey1</RefKey1>
        <RefKey2>RefKey2</RefKey2>
        <RefKey3>RefKey3</RefKey3>
      </Item>
      <Item>
        <ItemNo>2</ItemNo>
        <GIAccNo>GIAccNo</GIAccNo>
        <TaxCode>TaxCode</TaxCode>
        <Amount>Amount</Amount>
        <Currency>Currency</Currency>
        <Text>Text</Text>
        <CostCenter>CostCenter</CostCenter>
        <RefKey1>RefKey1</RefKey1>
        <RefKey2>RefKey2</RefKey2>
        <RefKey3>RefKey3</RefKey3>
      </Item>
    </DocumentBatch>
    

    【讨论】:

    • for $x in distinct-values(/root/r/Analysis_1_Codetext()) 可能会稍微快一些。此外,您不需要在原始 XML 中 SELECT *,只需要必要的列即可。
    • @Charlieface,我同意你的看法。目前尚不清楚最终 XML 中所有“常量”值的来源。
    猜你喜欢
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-14
    相关资源
    最近更新 更多