无法使FOR XML PATH正常工作

时间:2012-08-29 02:15:35

标签: sql sql-server

我正在努力弄清楚如何将XML PATH添加到我的代码中来连接一些信息,更不用说了解XML PATH的工作方式了。我花了最近两天的大部分时间来完成这项工作,并希望得到一些帮助!!

这是我正在使用的代码:

Select Top 100 Percent Agreements.AgrmntID, Agreements.Description As
  AgrmntDesc, Agreements.Status, AgreementSchedules.SchedDate, DateName(dw,
  AgreementSchedules.SchedDate), LaborCodeTypes.Description As LaborCode,
  Customers.CustName, Customers.CompanyName, JobSites.SiteName,
  AgreementSchedules.AgrmntSchedID
From Agreements Inner Join
  AgreementTypes On Agreements.AgrmntTypeID = AgreementTypes.AgrmntTypeID
  Inner Join
  AgreementSchedules On Agreements.AgrmntID = AgreementSchedules.AgrmntID
  Inner Join
  Customers On Agreements.CustID = Customers.CustID Inner Join
  JobSites On Agreements.CustSiteID = JobSites.CustSiteID Left Outer Join
  LaborCodeTypes On AgreementSchedules.RepairID = LaborCodeTypes.RepairID
Where Agreements.Status = 2 And Month(AgreementSchedules.SchedDate) =
  Month(GetDate())

示例数据:

| AgreementID | LaborCodeTypes.Description   | DateName(dw, AgreementSchedules.SchedDate)|
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| 1           | Landscaping                  | Tuesday                                   |
| 1           | Landscaping                  | Friday                                    |
| 1           | Sweeping                     | Monday                                    |
| 1           | Sweeping                     | Wednesday                                 |
| 1           | Sweeping                     | Friday                                    |
| 2           | Landscaping                  | Monday                                    |

预期产出:

| AgreementID | LaborCode   | Days Of Week              |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 1           | Landscaping | Tuesday, Friday           |
| 1           | Sweeping    | Monday, Wednesday, Friday |
| 2           | Landscaping | Monday                    |

如果有人能帮助我,我会非常感激。

提前谢谢!!

Jamie S

3 个答案:

答案 0 :(得分:3)

  

XML PATH如何工作

我将尝试使用此设置解释:

create table Grp
(
  GrpID int primary key,
  Name varchar(10)
)

create table Item
(
  ItemID int identity primary key,
  Name varchar(10),
  GrpID int references Grp(GrpID)
)

insert into Grp values
(1, 'G1'),
(2, 'G2')

insert into Item values
('A', 1),
('B', 1),
('C', 1),
('D', 2),
('E', 2)

目标是使用逗号分隔的每个组的名称列表创建结果。

GroupName  ItemNames
---------- ----------
G1         A,B,C
G2         D,E

FOR XML用于将查询结果转换为XML文档或XML片段。

此查询将创建XML片段。

select I.Name
from Item as I
for xml path(''), type

结果:

<Name>A</Name>
<Name>B</Name>
<Name>C</Name>
<Name>D</Name>
<Name>E</Name>

上面的查询可以在相关的子查询中使用,为这样的每个组创建XML片段。

select G.Name as GroupName,
       (
         select I.Name
         from Item as I
         where G.GrpID = I.GrpID
         for xml path(''), type
       ) as ItemNames
from Grp as G

结果:

GroupName  ItemNames
---------- --------------------------------------------
G1         <Name>A</Name><Name>B</Name><Name>C</Name>
G2         <Name>D</Name><Name>E</Name>

然后,您可以使用value()函数提取XML中的值。

select Name as GroupName,
       (
         select I.Name
         from Item as I
         where G.GrpID = I.GrpID
         for xml path(''), type
       ).value('.', 'varchar(max)') as ItemNames
from Grp as G

结果:

GroupName  ItemNames
---------- ----------
G1         ABC
G2         DE

要完成此操作,您需要添加逗号作为分隔符,并且可以通过向子查询select ','+I.Name中的每个项目名称添加逗号来完成。它将在第一个值之前为您留下额外的逗号。您可以使用STUFF功能删除STUFF(Value, 1, 1, '')

最终查询:

select Name as GroupName,
       stuff((
         select ','+I.Name
         from Item as I
         where G.GrpID = I.GrpID
         for xml path(''), type
       ).value('.', 'varchar(max)'), 1, 1, '') as ItemNames
from Grp as G

答案 1 :(得分:2)

;with C as
(
  select A.AgreementID,
         LCT.Description as LaborCode,
         Ags.ShedDate
  from Agreements as A
    inner join AgreementSchedules as AgS
      on A.AgreementID = AgS.AgreementID
    inner join LaborCodeTypes as LCT
      on AgS.RepairID = LCT.RepairID
  where A.[Status] = 2 and
        AgS.ShedDate >= dateadd(month, datediff(month, 0, getdate()), 0) and
        AgS.ShedDate < dateadd(month, 1+datediff(month, 0, getdate()), 0)
)
select C1.AgreementID,
       C1.LaborCode,
       stuff((select ', '+datename(weekday, C2.ShedDate)
              from C as C2
              where C1.AgreementID = C2.AgreementID and
                    C1.LaborCode = C2.LaborCode
              order by C2.ShedDate
              for xml path(''), type).value('.', 'varchar(max)'), 1, 2, '') as [Days Of Week]
from C as C1
group by C1.AgreementID, C1.LaborCode;

SQL Fiddle

答案 2 :(得分:0)

我相信我有不同的方法来实现您正在寻找的结果......

SELECT * FROM (
    SELECT DISTINCT AgreementId, UPPER(Description), 1 AS IsLabor
    FROM Table
    WHERE ...
    UNION
    SELECT AgreementId, DateName AS Description, 0 AS IsLabor
    FROM Table
    WHERE ...
) x
ORDER BY AgreementId, IsLabor DESC, Description

这应该输出以下内容(UPPER只是为了强调劳动描述):

| AgreementId | Description | IsLabor |
---------------------------------------
| 1           | LANDSCAPING | 1       |
| 1           | Friday      | 0       |
| 1           | Tuesday     | 0       |
| 2           | SWEEPING    | 1       |
| 2           | Friday      | 0       |
| 2           | Monday      | 0       |
| 2           | Wednesday   | 0       |

希望我理解你的问题,这将有效。