我的SQL小提琴就在这里:http://sqlfiddle.com/#!3/d5c60
CREATE TABLE customer
(
id int identity primary key,
name varchar(20),
);
CREATE TABLE warehouse
(
id int identity primary key,
name varchar(20),
);
CREATE TABLE customerwarehouse
(
id int identity primary key,
customerid int,
warehouseid int
);
INSERT INTO customer (name)
VALUES
('CustA'),
('CustB'),
('CustC');
INSERT INTO warehouse (name)
VALUES
('wh01'),
('wh02'),
('wh03');
INSERT INTO customerwarehouse (customerid, warehouseid)
VALUES
(1,1),
(2,1),
(2,2),
(3,1),
(3,2),
(3,3);
我想写一个查询以按以下格式返回客户/仓库数据:
Customer WH1 WH2 WH3
CustA wh01
CustB wh01 wh02
CustC wh01 wh02 wh03
我尝试这样做会为所有仓库返回null。
如何构建查询以返回所需格式的数据?
答案 0 :(得分:5)
为了获得结果,您需要加入表并应用PIVOT函数。我还建议使用row_number()
窗口函数来获取每个客户的仓库数量 - 这将是将用作新列标题的值。
select customername, wh1, wh2, wh3
from
(
select w.name warehousename,
c.name customername,
'wh'+cast(row_number() over(partition by c.id
order by w.id) as varchar(10)) seq
from customer c
inner join customerwarehouse cw
on c.id = cw.customerid
inner join warehouse w
on cw.warehouseid = w.id
) d
pivot
(
max(warehousename)
for seq in (wh1, wh2, wh3)
) piv;
见SQL Fiddle with Demo。如果您具有未知数量的值,则需要使用动态SQL来获取结果:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME('wh'+cast(row_number() over(partition by customerid
order by warehouseid) as varchar(10)))
from customerwarehouse
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT customername, ' + @cols + '
from
(
select w.name warehousename,
c.name customername,
''wh''+cast(row_number() over(partition by c.id
order by w.id) as varchar(10)) seq
from customer c
inner join customerwarehouse cw
on c.id = cw.customerid
inner join warehouse w
on cw.warehouseid = w.id
) x
pivot
(
max(warehousename)
for seq in (' + @cols + ')
) p '
execute sp_executesql @query;
见SQL Fiddle with Demo。两者都给出了结果:
| CUSTOMERNAME | WH1 | WH2 | WH3 |
| CustA | wh01 | (null) | (null) |
| CustB | wh01 | wh02 | (null) |
| CustC | wh01 | wh02 | wh03 |
答案 1 :(得分:0)
这是我在this MSDN page上查看复杂PIVOT示例后想出的:
SELECT
CustomerName,
case when [wh01] is null then null else 'wh01' end,
case when [wh02] is null then null else 'wh02' end,
case when [wh03] is null then null else 'wh03' end
FROM (
SELECT
c.Name AS CustomerName,
cw.id AS cwid,
w.name AS WarehouseName
FROM Customer c
JOIN CustomerWarehouse cw
ON c.id = cw.customerId
JOIN Warehouse w
ON w.id = cw.warehouseId
) AS SourceTable
pivot (
max(cwid)
FOR WarehouseName IN (
[wh01], [wh02], [wh03]
)
) AS PivotTable
在SQLFiddle上:http://sqlfiddle.com/#!3/d5c60/42