首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将行转换为具有指定列名的列?

如何将行转换为具有指定列名的列?
EN

Stack Overflow用户
提问于 2020-03-12 01:29:59
回答 3查看 85关注 0票数 0

我想要构造一个查询来映射产品及其相关图片,以匹配目标数据库模式。我的源数据库使用Product_Picture_Mapping作为双向映射表将每个产品的SEO存储在图片表中。因此,每个产品表都可以有0到n张与其相关联的图片。

代码语言:javascript
运行
复制
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作为字段存储。这使得编写查询相当困难,因为我需要将源的行转换为如下所示的命名列:

代码语言:javascript
运行
复制
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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-03-12 01:58:38

我建议user Pivot函数与ROW_NUMBER()一起使用(按名称划分,按SeoFilename订购价格)

代码语言:javascript
运行
复制
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
    );
  • "ROW_NUMBER() OVER (按名称划分,SeoFilename命令价格)“根据不同的名称和价格为每一行创建了序列号("1”、"2“、"3”等)。
  • Pivot函数将根据从seqnum列给出的序列号,按名称和价格转换结果。
  • min聚合函数实际上什么也不做,因为在相同的名称和价格下,每个seqnum只有一个SeoFilename。它只是为了充分满足枢轴功能的要求。
票数 0
EN

Stack Overflow用户

发布于 2020-03-12 01:38:23

我认为您需要有条件的聚合:

代码语言:javascript
运行
复制
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。

票数 0
EN

Stack Overflow用户

发布于 2020-03-12 11:59:52

诀窍是双重的。首先,您需要添加一种按名称划分数据的方法。罗号码会在这方面有所帮助的。第二,你需要改变旧的时尚方式。

行号是窗口函数,您可以向它添加一个分区。需要这个分区来确定某物是否是第一、第二、第三转置列。此方法的唯一缺点是需要硬编码转置列的数量。

旧式的枢轴在陈述时用一组一组的方式工作。为了避免所需的聚合,您可以使用MAX语句,因为在这种情况下,基本上会忽略max语句。

代码语言:javascript
运行
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60646476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档