Объединить строки из таблиц с перекрестными ссылками

Я хотел бы создать оператор SQL Server select, в котором данные перекрестных ссылок находятся в одном столбце из разных строк. Я бы хотел использовать stuff (если возможно) и не использовать команду ;with.

Таблица Контракт

ID  Subject
1   a
2   b
3   c

Таблица Компания

ID  Name
1   a_ltd
2   b_ltd
3   c_ltd
4   d_ltd
5   e_ltd

Таблица ContractContractorCrossRef (соединительная таблица)

ID  ContractID_ CompanyID_
1   1               1
2   1               2
3   2               3
4   3               1
5   3               4
6   3               5

Я хотел бы этот результат:

Contract.ID company.Name
1           a_ltd, b_ltd
2           c_ltd
3           a_ltd, d_ltd, e_ltd

Заполнить данные:

create table #Contract (ID INT, Subject VARCHAR(1))
INSERT  #Contract
SELECT  1, 'a' UNION ALL
SELECT  2, 'b' UNION ALL
SELECT  3, 'c'

create table #Company (ID INT, Name VARCHAR(5))
INSERT  #Company
SELECT  1, 'a_ltd' UNION ALL
SELECT  2, 'b_ltd' UNION ALL
SELECT  3, 'c_ltd' UNION ALL
SELECT  4, 'd_ltd' UNION ALL
SELECT  5, 'e_ltd'

create table #ccRef (ID INT, ContractID_ INT, CompanyID_ INT)
INSERT  #ccRef
SELECT  1, 1, 1 UNION ALL
SELECT  2, 1, 2 UNION ALL
SELECT  3, 2, 3 UNION ALL
SELECT  4, 3, 1 UNION ALL
SELECT  5, 3, 4 UNION ALL
SELECT  6, 3, 5 

Выберите:

select #Contract.ID, #Company.Name from #Contract
inner join #ccRef on #Contract.ID = #ccRef.ContractID_ inner join #Company
on #ccRef.CompanyID_ = #Company.ID

Выберите результат: (не требуется)

ID  Name
1   a_ltd
1   b_ltd
2   c_ltd
3   a_ltd
3   d_ltd
3   e_ltd

Запрошенный результат:

Contract.ID company.Name
1           a_ltd, b_ltd
2           c_ltd
3           a_ltd, d_ltd, e_ltd

person Satu    schedule 26.07.2012    source источник
comment
Что вы пробовали?   -  person marc_s    schedule 26.07.2012
comment
Почему ваши требования включают stuff и не включают CTE?   -  person Aaron Bertrand    schedule 26.07.2012
comment
Я много читал о XML Path и STUFF, чтобы сделать это решение.   -  person Satu    schedule 26.07.2012


Ответы (2)


Попробуй это. Я не тестировал код, так как у меня нет ddl для этих таблиц. Но он должен работать.

       SELECT ct.id ,
 left(companyname.value('.','varchar(max)'), len(companyname.value('.','varchar(max)'))-1) as companyname 
from 
    contract ct 
    cross apply 
    ( 
    select cm.name + ',' [text()]
    from 
    contractcompanycrossref cc 

    inner join company cm
    on cc.companyid = cm.ID
      where ct.id = cc.contractid 
    for xml path (''),type
    ) cmnames(companyname)
person Gulli Meel    schedule 26.07.2012
comment
Что-то не так с синтаксисом, но у меня уже есть решение. Спасибо. Сообщение 156, уровень 15, состояние 1, строка 10 Неверный синтаксис рядом с ключевым словом «включено». - person Satu; 26.07.2012
comment
Извините, попробуйте сейчас, я проверил ссылку, предоставленную вами..sqlfiddle.com/#!3/f3004/18 - person Gulli Meel; 26.07.2012
comment
Это работает. Спасибо. У вас есть идеи, почему результат вместо символа & (амперсанд), когда символ & находится в названии компании. Это сопоставление? (База данных: 'a<d' - Результат: 'altd' - person Satu; 26.07.2012
comment
Это связано с xml, но в приведенной выше ссылке не отображается amp; - person Gulli Meel; 26.07.2012
comment
Он отлично работает по ссылке выше, но на сервере sql нет. Я нашел статью об этом: sqlblog.com/blogs/rob_farley/archive/2010/04/15/ - person Satu; 26.07.2012
comment
Вы мастер! Благодарю вас! - person Satu; 27.07.2012

Вы можете сделать следующее:

SELECT x.id
  , left(CompanyName, len(CompanyName)-1) as CompanyName
FROM
(
  SELECT DISTINCT ct.id
    , (SELECT CAST(co.Name + ', ' AS VARCHAR(MAX)) 
           FROM contractcompanycrossref cc
           LEFT JOIN company co
            on cc.companyid = co.id
           WHERE (cc.contractid = ct.id) 
           FOR XML PATH ('')
        ) AS CompanyName
  from contract ct
  left join contractcompanycrossref cc
    on ct.id = cc.contractid
) x

См. SQL Fiddle с демонстрацией.

person Taryn    schedule 26.07.2012
comment
Вот мой результат:‹br/› id CompanyName ‹br/› 1 a_ltd ‹br/› 2 b_ltd ‹br/› 3 c_ltd ‹br/› - person Satu; 26.07.2012
comment
Вы видели мою SQL Fiddle? Он дает результаты, о которых вы просили. - person Taryn; 26.07.2012