我有三个具有以下结构的表(商店,销售和产品):
--Stores
IdStore StoreName
1A Store A
2B Store B
3C Store C
-- Products
IdProduct Desc
1G Product 1
2A Product 2
3A Product 3
4A Product 4
--Sales
TicketNo Store Product Qty
1001 Store A Product 1 10
1002 Store A Product 1 10
1003 Store B Product 3 50
1004 Store A Product 2 20
1005 Store A Product 3 5
1006 Store B Product 1 30
目前,我有以下查询:
SELECT S.StoreName, sum(SA.Qty), P.Desc
FROM SALES SA
cross apply (select top 1 * from Stores S where SA.Store = S.StoreName) S
cross apply (select top 1 * from Products P where SA.Product = P.Desc) P
group by S.StoreName, P.Desc
根据上述表结构和数据,查询结果如下:
-- output
StoreName Qty Desc
Store A 20 Product 1
Store A 20 Product 2
Store A 5 Product 3
Store B 30 Product 1
Store B 20 Product 2
我的问题是,是否存在一种获得相同结果但顺序不同的方法,以及是否有可能从同一行的一个商店中获取所有结果,像这样:
Store Product 1 Product 2 Product 3
Store A 20 20 5
Store B 30 20 0
或类似的东西
Store Result (in same line)
Store A 20;20;5;
Store B 30;20;0;
答案 0 :(得分:2)
首先,您应该使用INNER JOIN
而不是交叉应用:
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等按商店和产品对数据进行分组,然后根据该数据生成表行。如果使用了像Entity Framework这样的ORM,则数据将已经处于适当的结构中。
生成所需表可以使用两个循环,例如:
<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();
并使用它们来循环生成标头
答案 1 :(得分:1)
您在这里。您将需要PIVOT
函数,但需要定义产品的名称。
在下面查看样机:
DECLARE @Stores TABLE(IdStore VARCHAR(100),[StoreName] VARCHAR(100));
INSERT INTO @Stores
--Stores
select '1A','Store A' UNION ALL
select '2B','Store B' UNION ALL
select '3C','Store C'
DECLARE @Products TABLE(IdProduct VARCHAR(100),[Desc] VARCHAR(100));
INSERT INTO @Products
-- Products
select '1G','Product 1' UNION ALL
select '2A','Product 2' UNION ALL
select '3A','Product 3' UNION ALL
select '4A',' Product 4'
DECLARE @Sales TABLE(TicketNo INT, Store VARCHAR(100),[Product] VARCHAR(100), Qty INT);
INSERT INTO @Sales
--Sales
select '1001','Store A','Product 1','10' UNION ALL
select '1002','Store A','Product 1','10' UNION ALL
select '1003','Store B','Product 3','50' UNION ALL
select '1004','Store A','Product 2','20' UNION ALL
select '1005','Store A','Product 3','5' UNION ALL
select '1006','Store B','Product 1','30'
SELECT p.*
FROM
(
SELECT S.StoreName, SA.Qty, P.[Desc]
FROM
@SALES SA
left join @Stores S on SA.Store = S.StoreName
left join @Products P on SA.Product = P.[Desc]
)t
PIVOT
(
SUM(Qty) FOR [Desc] IN ([Product 1],[Product 2],[Product 3] /*add as many as you need*/)
)p;