Vous ne pouvez pas avoir un nombre dynamique de colonnes comme ça, mais vous pouvez concaténer vos données en chaîne :
select
s.ItemID, s.Code, s.Name,
stuff(
(
select ', ' + CAST(sv.SearchValueID AS VARCHAR)
from ItemSearch as sv
where sv.ItemID = s.ItemID
for xml path(''), type
).value('.', 'nvarchar(128)')
, 1, 2, '') as SearchValues
from Item as s;
ou vous pouvez faire pivoter les lignes avec PIVOT command
ou manuellement (Je préfère cette dernière approche, cela me semble juste plus flexible, mais pivot
peut réduire considérablement la quantité de code dans certaines situations ):
with cte as (
select
*,
row_number() over(partition by sv.ItemID order by sv.SearchValueID) as row_num
from ItemSearch as sv
)
select
s.ItemID, s.Code, s.Name,
max(case when sv.row_num = 1 then sv.SearchValueID end) as SearchValueID1,
max(case when sv.row_num = 2 then sv.SearchValueID end) as SearchValueID2,
max(case when sv.row_num = 3 then sv.SearchValueID end) as SearchValueID3,
max(case when sv.row_num = 4 then sv.SearchValueID end) as SearchValueID4
from Item as s
inner join cte as sv on sv.ItemID = s.ItemID
group by s.ItemID, s.Code, s.Name
Vous pouvez également transformer l'instruction précédente en SQL dynamique comme ceci :
declare @stmt nvarchar(max)
select
@stmt =
isnull(@stmt + ',','') +
'max(case when sv.row_num = ' + cast(rn as nvarchar(max)) +
' then sv.SearchValueID end) as SearchValueID' + cast(rn as nvarchar(max))
from (
select distinct row_number() over(partition by ItemID order by SearchValueID) as rn
from ItemSearch
) as a
select @stmt = '
with cte as (
select
*,
row_number() over(partition by sv.ItemID order by sv.SearchValueID) as row_num
from ItemSearch as sv
)
select
s.ItemID, s.Code, s.Name,' + @stmt + '
from Item as s
inner join cte as sv on sv.ItemID = s.ItemID
group by s.ItemID, s.Code, s.Name;'
exec dbo.sp_executesql @stmt = @stmt