Прежде всего, вы должны использовать INNER JOIN
, а не CROSS APPLY:
SELECT S.StoreName, P.Desc,sum(SA.Qty) as QTY
FROM SALES SA
INNER JOIN Stores S ON SA.Store = S.StoreName
INNER JOIN Products P ON SA.Product = P.Desc
group by S.StoreName, P.Desc
Если количество столбцов известно заранее, вы можете преобразовать строки в столбцы с помощью оператора PIVOT:
SELECT S.StoreName, [Product 1], [Product 2], [Product 3]
FROM
( SELECT SA.StoreName, P.Desc,SA.Qty
FROM SALES SA
INNER JOIN Stores S ON SA.Store = S.StoreName
INNER JOIN Products P ON SA.Product = P.Desc
) Q
PIVOT
(
SUM(Qty)
FOR Q.Desc IN ([Product 1], [Product 2], [Product 3])
) AS pvt
ORDER BY StoreName
Честно говоря, вероятно, было бы проще создать соответствующую таблицу на клиенте.PIVOT не может обрабатывать произвольное количество столбцов.В ASP.NET, с другой стороны, можно использовать, например, LINQ для группировки данных по магазинам и продуктам, а затем генерировать строки таблицы на основе этого.Если используется ORM-подобная Entity Framework, данные уже будут в правильной структуре.
Для создания необходимой таблицы можно использовать два цикла, например:
<thead>
<tr>
<th>Store Name</th>
<th>Product 1</th>
...
</tr>
</thead>
@foreach(var store in Model.Stores)
{
<tr>
<td>@store.StoreName</td>
@foreach(var product in store.Products.OrderBy(p=>p.Desc))
{
<td>@product.Qty</td>
}
</tr>
}
Вы можете получить весь продуктимена с LINQ, например, с:
var productNames = Stores.SelectMany(store=>store.Products)
.Select(p=>p.Desc)
.Distinct()
.OrderBy(desc=>desc)
.ToArray();
И использовать их для генерации самих заголовков в цикле