我想要构造一个查询来映射产品及其相关图片,以匹配目标数据库模式。我的源数据库使用Product_Picture_Mapping作为双向映射表将每个产品的SEO存储在图片表中。因此,每个产品表都可以有0到n张与其相关联的图片。
SELECT
Name, Price, SeoFilename
FROM Product prod
JOIN Product_Picture_Mapping map
ON prod.Id = map.ProductId
JOIN Picture pict
ON pict.Id = map.PictureId
Name Price SeoFilename
-----------------------------------
Strawberries 11 strawberry
Strawberries 11 strawberry_1
Pineapples 10 pineapples
Banana 10 banana
Banana 10 banana_1
Orange 11 orange
不幸的是,目标数据库的产品表有0到3个SEO URL作为字段存储。这使得编写查询相当困难,因为我需要将源的行转换为如下所示的命名列:
Name Price MainImageUrl OtherImageUrl1 OtherImageUrl2
Banana 10 banana banana_1 null
Orange 11 orange null null
Pineapples 10 pineapples null null
Strawberries 11 Strawberry Strawberry_1 null
我尝试过使用推荐的枢轴函数,但它只能生成聚合值,因为它需要一个聚合函数。我见过其他方法,但它们通常是子查询的单个联接。
这里有一个指向我的数据库小提琴的链接:2019&fiddle=786b419936007c85f7f71f0defe5b829
发布于 2020-03-12 01:58:38
我建议user Pivot函数与ROW_NUMBER()一起使用(按名称划分,按SeoFilename订购价格)
With temp as (
SELECT
Name,
Price,
SeoFilename,
ROW_NUMBER() OVER (partition by Name, Price ORDER BY SeoFilename) as seqnum
FROM
Product prod
JOIN Product_Picture_Mapping map
ON prod.Id = map.ProductId
JOIN Picture pict
ON pict.Id = map.PictureId
)
select
Name,
price,
"1" as MainImageUrl,
"2" as OtherImageUrl1,
"3" as OtherImageUrl2,
"4" as OtherImageUrl3,
"5" as OtherImageUrl4
from
Temp
pivot
(
min(SeoFilename)
for seqnum in ( 1,2,3,4,5 ) -- Depends on how deep is it
);
发布于 2020-03-12 01:38:23
我认为您需要有条件的聚合:
SELECT Name, Price,
MAX(CASE WHEN seqnum = 1 THEN SeoFilename END) as SeoFilename_1,
MAX(CASE WHEN seqnum = 2 THEN SeoFilename END) as SeoFilename_2,
MAX(CASE WHEN seqnum = 3 THEN SeoFilename END) as SeoFilename_3,
MAX(CASE WHEN seqnum = 4 THEN SeoFilename END) as SeoFilename_4
FROM (SELECT Name, Price, SeoFilename,
ROW_NUMBER() OVER (ORDER BY name, price SeoFilename) as seqnum
FROM Product p JOIN
Product_Picture_Mapping ppm
ON p.Id = ppm.ProductId JOIN
Picture pic
ON pic.Id = ppm.PictureId
) pi
GROUP BY Name, Price;
这并不能准确地产生问题中的结果集。但我认为这是你想要的。
这里是db<>fiddle。
发布于 2020-03-12 11:59:52
诀窍是双重的。首先,您需要添加一种按名称划分数据的方法。罗号码会在这方面有所帮助的。第二,你需要改变旧的时尚方式。
行号是窗口函数,您可以向它添加一个分区。需要这个分区来确定某物是否是第一、第二、第三转置列。此方法的唯一缺点是需要硬编码转置列的数量。
旧式的枢轴在陈述时用一组一组的方式工作。为了避免所需的聚合,您可以使用MAX语句,因为在这种情况下,基本上会忽略max语句。
if OBJECT_ID('tempdb..#test') is not null
begin
drop table #test
end
create table #test
(
name varchar(50)
,price int
,seofilename varchar(50)
)
insert into #test
values
('apple', 10, 'apple1'),
('apple',10,'apple4'),
('pear',23,'pear1'),
('pear',23,'pear5'),
('banana',56,'banan9'),
('banana',56,'banan6'),
('banana',56,'banan')
select
name,
price,
max(case when rownum = 1 then seofilename else null end) as PrimaryFileName,
max(case when rownum = 2 then seofilename else null end) as SecondaryFileName,
max(case when rownum = 3 then seofilename else null end) as TertiaryFileName
from
(
select
name,
price,
seofilename,
ROW_NUMBER() over (partition by name order by name) as rownum
from
#test
) Q
group by
name,
price
https://stackoverflow.com/questions/60646476
复制相似问题