SQL Server 2005 - TSQL для запросов XML для получения сгруппированных отделов и сотрудников - PullRequest
2 голосов
/ 18 января 2012

Для базы данных, содержащей 3 таблицы:

  1. Компания
  2. Отдел
  3. EmployeeInDepartment

Я хотел бы, чтобы XML какниже:

<Companies>
  <Company>
    <CompanyName></CompanyName>
    <CompanyId></CompanyId>
    <..></..>
    <Departments>
       <Name></Name>
       <..></..>
       <Employees>
          <Employee>
             <FirstName></FirstName>
             <LastName></LastName>
             .. .. ..
          </Employee>
          .. .. ..
       </Employees>
    </Departments>
    .. .. ..
  </Company>
  .. .. .. 
</Companies>

В тех случаях, когда компания повторяет (теги), департаменты внутри компании повторяют (теги), а сотрудники внутри департаментов повторяют (теги), повторяя. Я имею в виду, что существует более одного числа этих элементови не данные.

Отношения

  1. Company и Department связаны через FK inТаблица Department, которая ссылается на CompanyId в таблице Company.

  2. Department и EmployeeInDepartment связаны через 'FK' в таблице EmployeeInDepartment, которая ссылается на DepartmentId в Department таблице.

Запрос:

выполните приведенное ниже в базе данных PUBS и проверьте xml, в нем будет более одного задания с идентификатором 10

select jobs.job_id 'JobId',
job_desc 'Desc',
(
    select emp_id 'EmployeeId',fname 'FirstName',lname 'LastName' from employee where job_id = jobs.job_id for xml path('Emploees'),type
)
from jobs
inner join 
employee on  jobs.job_id = employee.job_id
for xml path('employees')

Ответы [ 2 ]

3 голосов
/ 18 января 2012

Вы должны делать «вложенные» FOR XML утверждения - это должно дать вам то, что вы ищете.

SELECT
   (some 'Company' columns),
   (SELECT
       (some 'Department' columns),
       (SELECT
           (some 'Employee' columns),
        FROM dbo.EmployeeInDepartment e
        WHERE e.DepartmentId = d.DepartmentId
        FOR XML PATH('Employee'), TYPE
       ) AS 'Employees'
    FROM dbo.Department d
    WHERE d.CompanyId = c.CompanyId
    FOR XML PATH('Department'), TYPE
   ) AS 'Departments'
FROM dbo.Company c
FOR XML PATH('Company'), ROOT('Companies')

См. Например Результаты вложенного FOR XML Ричарда Дингволла с SQL Server , который показывает, как это сделать. Конечно, вы можете легко вкладывать более двух уровней ...

2 голосов
/ 18 января 2012

Не совсем уверен, как вы этого хотите, но это должно дать вам начало.

declare @jobs table
(
  job_id int,
  job_desc varchar(10)
)

declare @employee table
(
  emp_id int,
  fname varchar(10),
  lname varchar(10),
  job_id int
)

insert into @jobs values
(1, 'Job 1'),
(2, 'Job 2')

insert into @employee values
(1, 'first 1', 'last 1', 1),
(2, 'first 2', 'last 2', 1),
(3, 'first 3', 'last 3', 2)

select employee.emp_id 'EmployeeId',
       employee.fname 'FirstName',
       employee.lname 'LastName',
       (
        select jobs.job_id 'JobId',
               jobs.job_desc 'Desc'
        from @jobs jobs
        where jobs.job_id = employee.emp_id
        for xml path('jobs'),type        
       )
from @employee employee
for xml path('employees')

Результат:

<employees>
  <EmployeeId>1</EmployeeId>
  <FirstName>first 1</FirstName>
  <LastName>last 1</LastName>
  <jobs>
    <JobId>1</JobId>
    <Desc>Job 1</Desc>
  </jobs>
</employees>
<employees>
  <EmployeeId>2</EmployeeId>
  <FirstName>first 2</FirstName>
  <LastName>last 2</LastName>
  <jobs>
    <JobId>2</JobId>
    <Desc>Job 2</Desc>
  </jobs>
</employees>
<employees>
  <EmployeeId>3</EmployeeId>
  <FirstName>first 3</FirstName>
  <LastName>last 3</LastName>
</employees>

Вы не должны объединять все свои столы в каждой части. Основной запрос запрашивает только ту информацию, которая необходима для корневого уровня, а подзапросы запрашивают только необходимую информацию с предложением where where jobs.job_id = employee.emp_id, которое фильтрует строки в подзапросах, так что вы получаете только те строки, которые вам нужны в дочерние узлы.

...