【问题标题】:OPENXML with Left Join带有左连接的 OPENXML
【发布时间】:2016-09-12 12:10:56
【问题描述】:

我在 SQL Server 2008 中有 2 个表,分别称为“User”和“UserDetail”。主表“User”包含以下列

UserId Int, 
UserDate DateTime, 
ModifiedBy Int

“UserDetail”表包含以下列

UserId Int
,UserIdDetailId Int
,Amount Int
,Balance Int

User表包含如下数据

 UserId UserDate    ModifiedBy
 101  "01-Jan-2016" 100
 102  "01-Feb-2016" 200
 103  "01-Mar-2016" 300

UserDetail 表包含的数据为

 UserId UserDetailId Amount Balance
 101  1001  10 2
 102  1002  20 4

对于 User 表的第 3 行,它在 UserDetail 表中没有子记录。

现在我想使用 sp 从 User 和 UserDetail 表中检索记录

在前端asp.net中,我将xml框起来并传递给sql sp。

<root>
<rec UserId="101" UserDate="8/22/2016 12:00:00 AM" ModifiedBy="8/22/2016 01:10:59 PM" userdetails="System.Collections.Generic.List`1[UserDetail]">
    <userdetail userdetailid="1001" amount="10" balance="2"  />
</rec>
<rec userid="102" userdate="8/22/2016 12:00:00 AM" modifiedby="8/22/2016 01:10:59 PM" userdetails="System.Collections.Generic.List`1[UserDetail]">
    <userdetail userdetailid="1001" amount="1=20" balance="4" />
</rec>
<rec userid="103" userdate="8/22/2016 12:00:00 AM" modifiedby="8/22/2016 01:10:59 PM" userdetails="System.Collections.Generic.List`1[UserDetail]" />

sql sp中的openxml如下

SELECT *
INTO #temp
FROM (
SELECT  m.UserId,
    m.UserDate,
    m.ModifiedBy,
    COALESCE(det.UserDetailId, -1) as UserDetailId
FROM OPENXML(@i, '/Root/Rec', 1) WITH (
   ,UserId INT '@UserId'
   ,UserDate DATETIME '@UserDate'
   ,ModifiedBy INT '@ModifiedBy'
) as m
LEFT JOIN (
SELECT  UserId,
        UserDetailId
FROM OPENXML(@i, '/Root/Rec/UserDetail', 1) WITH (
         UserId INT '@UserId'
        ,UserIdDetailId INT '@UserIdDetailId'
    ,Amount INT '@Amount'
    ,Balance INT '@Balance'
        )
) as det
ON m.UserId =det.UserId

)p

我希望它按如下方式存储在#temp 表中

UserId UserDetailId  UserDate       ModifiedBy Amount Balance
101    1001          "01-Jan-2016"  100        10     2
102    1002          "01-Feb-2016"  200        20     4
103    1003          "01-Mar-2016"  300        NULL   NULL

我也想在此表中获取 103 UserId,其中详细值为 NULL

我的问题是如何构建 OPENXML 以使用 OPENXML 中的联接从 User 和 UserDetail 表中获取所有记录,我对 OPENXML 及其联接不满意,但不知何故我希望它能够正确执行。强>

【问题讨论】:

  • 现在我从明细表中获取所有 NULL

标签: c# sql asp.net sql-server


【解决方案1】:

首先添加AmountBalance,这样就可以选择这个字段了:

SELECT *
INTO #temp
FROM (
    SELECT  m.UserId,
            m.UserDate,
            m.ModifiedBy,
            COALESCE(det.UserDetailId, -1) as UserDetailId,
            det.Amount,
            det.Balance
    FROM OPENXML(@i, '/Root/Rec', 1) WITH (
       UserId INT '@UserId',
       UserDate DATETIME '@UserDate',
       ModifiedBy INT '@ModifiedBy'
) as m
LEFT JOIN (
SELECT  UserId,
        UserDetailId,
        Amount,
        Balance
FROM OPENXML(@i, '/Root/Rec/UserDetail', 1) WITH (
    UserId INT '../@UserId',
    userdetailid INT '../@UserDetailId',
    Amount INT '@Amount',
    Balance INT '@Balance'
    )
) as det
    ON m.UserId =det.UserId
) as p

至于你的问题,不清楚你想从这个连接中得到什么输出。

【讨论】:

  • 我从 xml 中的 UserDetail 记录中获取空值到 #temp 表
  • 您需要在 det 部分中使用 ../。改了答案。我已经向你展示了这个查询here。在我的回答中,我使用 ../ 从另一个级别获取 UserId 的值。
  • 我现在一团糟。例如,使用当前打开的 xml,它总共返回 40 行。但实际的 xml 数据包含 5 个主元素和 4+4 个子元素。 1 个标头 id 有 4 条记录,其他标头 id 有 4 条记录。理想情况下,我应该得到 8(detail)+3(header)rows = 11 行。此处应用了一些交叉连接。
  • 在您在此问题中发布的 XML 中,它有 3 个父元素和 2 个子元素 - 此查询按预期返回 3 行。如果 XML 将包含 5 个父元素,其中 2 个有 4 个子元素,则查询应返回 11 行。它是 LEFT JOIN - 不是 CROSS JOIN。我敢打赌,这与您的 XML 有关。或者 - 您在上面的查询中添加一些修改。
  • XML 可以带有 UserId 和 UserDetailId 作为标题行和详细信息行的零。这就是我得到 40 行的原因。有没有办法解决这个问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多