Кажется, работает следующий динамический запрос:
declare @columnlist nvarchar(4000)
select @columnlist = IsNull(@columnlist + ', ', '') + '[' + PositionName + ']'
from #Position
declare @query nvarchar(4000)
select @query = '
select *
from (
select CategoryId, CategoryName, PositionName,
IsNull(COrder,0) as COrder
from #Position p
cross join #Category c
left join #CategoryPosition cp
on cp.pid = p.PositionId
and cp.cid = c.CategoryId
) pv
PIVOT (max(COrder) FOR PositionName in (' + @columnlist + ')) as Y
ORDER BY CategoryId, CategoryName
'
exec sp_executesql @query
Некоторые уточнения:
- @columnlist содержит список полей с двоеточиями, построенный из таблицы Positions
- Перекрестное соединение создает список всех категорий и всех позиций
- Левое соединение ищет соответствующий код
- max () выбирает самый высокий COrder для категории + позиция, если существует более одного
- PIVOT () превращает различные PositionNames в отдельные столбцы
P.S. Мои имена таблиц начинаются с #, потому что я создал их как временные таблицы. Удалите # для ссылки на постоянную таблицу.
P.S.2. Если кто-то хочет попробовать свои силы в этом, вот скрипт для создания таблиц в этом вопросе:
set nocount on
if object_id('tempdb..#Category') is not null drop table #Category
create table #Category (
CategoryId int identity,
CategoryName varchar(50)
)
insert into #Category (CategoryName) values ('Home')
insert into #Category (CategoryName) values ('Contact')
insert into #Category (CategoryName) values ('About')
--insert into #Category (CategoryName) values ('News')
if object_id('tempdb..#Position') is not null drop table #Position
create table #Position (
PositionID int identity,
PositionName varchar(50)
)
insert into #Position (PositionName) values ('Main menu')
insert into #Position (PositionName) values ('Left menu')
insert into #Position (PositionName) values ('Right menu')
--insert into #Position (PositionName) values ('Bottom menu')
if object_id('tempdb..#CategoryPosition') is not null
drop table #CategoryPosition
create table #CategoryPosition (
CPID int identity,
CID int,
PID int,
COrder int
)
insert into #CategoryPosition (CID, PID, COrder) values (1,1,1)
insert into #CategoryPosition (CID, PID, COrder) values (1,2,2)
insert into #CategoryPosition (CID, PID, COrder) values (1,3,3)
insert into #CategoryPosition (CID, PID, COrder) values (2,1,4)
insert into #CategoryPosition (CID, PID, COrder) values (2,3,5)