如何合并Microsoft SQL Server的两个不同xpath的结果

时间:2017-02-21 04:19:46

标签: sql sql-server xml xpath sql-server-2016

我是新来的,所以请耐心等待。我有两个select语句,包含我想从Microsoft SQL Server 2016中的XML文档中获取的所有信息。我想组合这两个select语句的内容,然后将其转换为表。问题是xpath发散了。我不知道该怎么做。

这是我的第一个问题:

SELECT * 
FROM OPENXML (@hdoc, '/roll/bill', 1)
WITH (
[where] char(5) '../@where',
[session] tinyint '../@session',
[year] smallint '../@year',
roll smallint '../@roll',
[datetime] datetime '../@datetime',
number int)

这是我的第二个问题:

SELECT *
FROM OPENXML (@hdoc, '/roll/voter', 2)
WITH (
    id int '@id',
    [value] char(50) '@value',
    [state] char(2) '@state',
    [category] char(7)'../category',
    [type] varchar(1000)'../type',
    [question] varchar(1000)'../question',
    [result] varchar(20)'../result')

这是我的xml文档的婴儿大小版本:

<roll where="house" session="114" year="2015" roll="705" source="house.gov" datetime="2015-12-18T09:49:00-05:00" updated="2016-12-25T10:03:32-05:00" aye="316" nay="113" nv="5" present="0">
<category>passage</category>
<type>On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566</type>
<question>On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566: H R 2029 Making appropriations for military construction, the Department of Veterans Affairs, and related agencies for the fiscal year ending September 30, 2016, and for other purposes</question>
<required>1/2</required>
<result>Passed</result>
<bill session="114" type="h" number="2029" />
<option key="+">Yea</option>
<option key="-">Nay</option>
<option key="P">Present</option>
<option key="0">Not Voting</option>
<voter id="412607" vote="+" value="Yea" state="NC" />
<voter id="400004" vote="+" value="Yea" state="AL" />
<voter id="412615" vote="+" value="Yea" state="CA" />
<voter id="412625" vote="+" value="Yea" state="GA" />
</roll>

如果有人能够告诉我我需要做什么以及解释原因,我将不胜感激。

Here is a screenshot of my two select statements and their results

2 个答案:

答案 0 :(得分:2)

FROM OPENXML已过时,不应再使用了......(很少有例外)。更好地使用真正的XML方法。试试这个:

我假设,XML的上半部分是元数据,而<voter>元素是1:n - 相关的工作数据。因此,我的结果返回每个选民一行。我希望我能正确得到这个!

DECLARE @DummyTable TABLE(YourXML XML);
INSERT INTO @DummyTable VALUES
(
N'<roll where="house" session="114" year="2015" roll="705" source="house.gov" datetime="2015-12-18T09:49:00-05:00" updated="2016-12-25T10:03:32-05:00" aye="316" nay="113" nv="5" present="0">
  <category>passage</category>
  <type>On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566</type>
  <question>On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566: H R 2029 Making appropriations for military construction, the Department of Veterans Affairs, and related agencies for the fiscal year ending September 30, 2016, and for other purposes</question>
  <required>1/2</required>
  <result>Passed</result>
  <bill session="114" type="h" number="2029" />
  <option key="+">Yea</option>
  <option key="-">Nay</option>
  <option key="P">Present</option>
  <option key="0">Not Voting</option>
  <voter id="412607" vote="+" value="Yea" state="NC" />
  <voter id="400004" vote="+" value="Yea" state="AL" />
  <voter id="412615" vote="+" value="Yea" state="CA" />
  <voter id="412625" vote="+" value="Yea" state="GA" />
</roll>'
);

- 查询

SELECT --first level attributes
       r.value(N'@where',N'nvarchar(max)') AS roll_where
      ,r.value(N'@session',N'int') AS roll_session
      ,r.value(N'@updated',N'datetime') AS roll_updated

      --first level elements
      ,r.value(N'(category)[1]',N'nvarchar(max)') AS category
      ,r.value(N'(type)[1]',N'nvarchar(max)') AS [type]
      ,r.value(N'(result)[1]',N'nvarchar(max)') AS result

      --second level attributes
      ,r.value(N'(bill/@session)[1]',N'int') AS bill_session

      --named choice    
      ,r.value(N'(option[@key="+"])[1]',N'nvarchar(max)') AS option_plus
      ,r.value(N'(option[@key="-"])[1]',N'nvarchar(max)') AS option_minus
      ,r.value(N'(option[@key="P"])[1]',N'nvarchar(max)') AS option_P
      ,r.value(N'(option[@key="0"])[1]',N'nvarchar(max)') AS option_0

      --it seems to be, that your "voter" elements are a 1:n related list?
      --therefore I used a second CROSS APPLY with .nodes() to get them row-wise
      ,v.value(N'@id','int') AS voter_id
      ,v.value(N'@vote','nvarchar(max)') AS voter_vote
      ,v.value(N'@value','nvarchar(max)') AS voter_value
      ,v.value(N'@state','nvarchar(max)') AS voter_state
FROM @DummyTable AS dt
CROSS APPLY dt.YourXML.nodes(N'roll') AS A(r)
CROSS APPLY A.r.nodes(N'voter') AS B(v)

结果

+------------+--------------+-------------------------+----------+--------------------------------------------------------------------------------+--------+--------------+-------------+--------------+----------+------------+----------+------------+-------------+-------------+
| roll_where | roll_session | roll_updated            | category | type                                                                           | result | bill_session | option_plus | option_minus | option_P | option_0   | voter_id | voter_vote | voter_value | voter_state |
+------------+--------------+-------------------------+----------+--------------------------------------------------------------------------------+--------+--------------+-------------+--------------+----------+------------+----------+------------+-------------+-------------+
| house      | 114          | 2016-12-25 15:03:32.000 | passage  | On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566 | Passed | 114          | Yea         | Nay          | Present  | Not Voting | 412607   | +          | Yea         | NC          |
+------------+--------------+-------------------------+----------+--------------------------------------------------------------------------------+--------+--------------+-------------+--------------+----------+------------+----------+------------+-------------+-------------+
| house      | 114          | 2016-12-25 15:03:32.000 | passage  | On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566 | Passed | 114          | Yea         | Nay          | Present  | Not Voting | 400004   | +          | Yea         | AL          |
+------------+--------------+-------------------------+----------+--------------------------------------------------------------------------------+--------+--------------+-------------+--------------+----------+------------+----------+------------+-------------+-------------+
| house      | 114          | 2016-12-25 15:03:32.000 | passage  | On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566 | Passed | 114          | Yea         | Nay          | Present  | Not Voting | 412615   | +          | Yea         | CA          |
+------------+--------------+-------------------------+----------+--------------------------------------------------------------------------------+--------+--------------+-------------+--------------+----------+------------+----------+------------+-------------+-------------+
| house      | 114          | 2016-12-25 15:03:32.000 | passage  | On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566 | Passed | 114          | Yea         | Nay          | Present  | Not Voting | 412625   | +          | Yea         | GA          |
+------------+--------------+-------------------------+----------+--------------------------------------------------------------------------------+--------+--------------+-------------+--------------+----------+------------+----------+------------+-------------+-------------+

答案 1 :(得分:-1)

您希望将语句中的列组合起来怎么样?例如,由于您的第一个语句返回1行而第二个语句返回许多行,因此您可能希望第一个语句中的列出现在第二个语句中的列的每一行上。你可以这样做:

SELECT * 
FROM OPENXML (@hdoc, '/roll/bill', 1)
WITH (
[where] char(5) '../@where',
[session] tinyint '../@session',
[year] smallint '../@year',
roll smallint '../@roll',
[datetime] datetime '../@datetime',
number int)
,OPENXML (@hdoc, '/roll/voter', 2)
WITH (
    id int '@id',
    [value] char(50) '@value',
    [state] char(2) '@state',
    [category] char(7)'../category',
    [type] varchar(1000)'../type',
    [question] varchar(1000)'../question',
    [result] varchar(20)'../result')

结果:

where    session     year    roll    datetime                    number      id          value   state   category    type                                                                                question                                                                                                                                                                                                                                                                    result
house    114         2015    705     2015-12-18 14:49:00.000     2029        412607      Yea     NC      passage     On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566      On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566: H R 2029 Making appropriations for military construction, the Department of Veterans Affairs, and related agencies for the fiscal year ending September 30, 2016, and for other purposes    Passed
house    114         2015    705     2015-12-18 14:49:00.000     2029        400004      Yea     AL      passage     On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566      On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566: H R 2029 Making appropriations for military construction, the Department of Veterans Affairs, and related agencies for the fiscal year ending September 30, 2016, and for other purposes    Passed
house    114         2015    705     2015-12-18 14:49:00.000     2029        412615      Yea     CA      passage     On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566      On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566: H R 2029 Making appropriations for military construction, the Department of Veterans Affairs, and related agencies for the fiscal year ending September 30, 2016, and for other purposes    Passed
house    114         2015    705     2015-12-18 14:49:00.000     2029        412625      Yea     GA      passage     On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566      On Concurring in Senate Amdt with Amdt Specified in Section 3(a) of H.Res. 566: H R 2029 Making appropriations for military construction, the Department of Veterans Affairs, and related agencies for the fiscal year ending September 30, 2016, and for other purposes    Passed

只要您的第一个语句只返回一行,这将为您提供与第二个语句相同的行数。如果您的第一个语句将返回2行而第二个返回4,则返回8行:第一个表中的行的所有组合和第二个表中的行。这称为交叉连接

如果您希望每个语句中有超过1行,并且有一些明确的方法可以将每个语句中的行关联在一起,那么您需要内连接

我要停在这里,因为你似乎对SQL有一点了解,并且对XML的工作原理感到困惑。但如果您需要更多信息,请在评论中说明,我会尝试扩大答案。