将 SQL 服务器 table 转换为更规范化的版本
Pivoting a SQL Server table into a more normalized version
旋转(或取消旋转)下面 table 的最佳方法是什么:
CREATE TABLE dbo.Sections(
SectionId varchar(50) NOT NULL (PK),
Description varchar(255),
SubSectionIdA varchar(50),
SubSectionIdB varchar(50),
SubSectionIdC varchar(50),
SubSectionIdD varchar(50),
SubSectionIdE varchar(50)
);
并将其转换为如下模式:
CREATE TABLE dbo.NormalizedSections(
SectionId varchar(50) NOT NULL (FK and part of PK),
Description varchar(255),
SubSectionId varchar(50) NOT NULL (other part of PK),
Order int
);
所以 Sections
table 可以有这样的示例数据:
SectionId Description SubSectionIdA SubSectionIdB SubSectionIdC SubSectionIdD SubSectionIdE
--------------------------------------------------------------------------------------------------------------------------------------------------------
Sec-01A Special section NULL '' SubsectionA1 SubsectionA2 ''
Sec-02B Cheap seats CheapSeciton1 '' CheapSectionTop NULL LimitedView
Sec-01B VIP Special CourtsideSeatView NULL NULL NULL
这需要变成这样:
SectionId Description SubSectionId Order
-------------------------------------------------------------------------------
Sec-01A Special section SubsectionA1 1
Sec-01A Special section SubsectionA2 2
Sec-02B Cheap seats CheapSeciton1 1
Sec-02B Cheap seats CheapSectionTop 2
Sec-02B Cheap seats LimitedView 3
Sec-01B VIP Special 1
Sec-01B VIP CourtsideSeatView 2
有没有一种快速的方法可以做到这一点并将其加载到临时 table 中,并在 SQL 服务器中使用一些奇特的非游标 T-SQL?
如果是一次性工作,请尝试 UNPIVOT to convert the SubSectionId..N columns into rows. Then add a ROW_NUMBER() 结果以按部分和小节生成订单号
-- Unpivot the table.
SELECT unpvt.SectionId
, unpvt.Description
, unpvt.SubSection
, ROW_NUMBER() OVER(PARTITION BY SectionId ORDER BY SubSection) AS RowOrder
FROM
( SELECT SectionId
, Description
, SubSectionIdA
, SubSectionIdB
, SubSectionIdC
, SubSectionIdD
, SubSectionIdE
FROM Sections
) p
UNPIVOT
(
SubSection FOR SubSectionId
IN (SubSectionIdA
, SubSectionIdB
, SubSectionIdC
, SubSectionIdD
, SubSectionIdE
)
)AS unpvt
WHERE ISNULL(SubSection, '') <> ''
结果:
SectionId | Description | SubSection | RowOrder
:-------- | :-------------- | :---------------- | -------:
Sec-01A | Special section | SubsectionA1 | 1
Sec-01A | Special section | SubsectionA2 | 2
Sec-01B | VIP | CourtsideSeatView | 1
Sec-01B | VIP | Special | 2
Sec-02B | Cheap seats | CheapSeciton1 | 1
Sec-02B | Cheap seats | CheapSectionTop | 2
Sec-02B | Cheap seats | LimitedView | 3
另见 db<>fiddle
旋转(或取消旋转)下面 table 的最佳方法是什么:
CREATE TABLE dbo.Sections(
SectionId varchar(50) NOT NULL (PK),
Description varchar(255),
SubSectionIdA varchar(50),
SubSectionIdB varchar(50),
SubSectionIdC varchar(50),
SubSectionIdD varchar(50),
SubSectionIdE varchar(50)
);
并将其转换为如下模式:
CREATE TABLE dbo.NormalizedSections(
SectionId varchar(50) NOT NULL (FK and part of PK),
Description varchar(255),
SubSectionId varchar(50) NOT NULL (other part of PK),
Order int
);
所以 Sections
table 可以有这样的示例数据:
SectionId Description SubSectionIdA SubSectionIdB SubSectionIdC SubSectionIdD SubSectionIdE
--------------------------------------------------------------------------------------------------------------------------------------------------------
Sec-01A Special section NULL '' SubsectionA1 SubsectionA2 ''
Sec-02B Cheap seats CheapSeciton1 '' CheapSectionTop NULL LimitedView
Sec-01B VIP Special CourtsideSeatView NULL NULL NULL
这需要变成这样:
SectionId Description SubSectionId Order
-------------------------------------------------------------------------------
Sec-01A Special section SubsectionA1 1
Sec-01A Special section SubsectionA2 2
Sec-02B Cheap seats CheapSeciton1 1
Sec-02B Cheap seats CheapSectionTop 2
Sec-02B Cheap seats LimitedView 3
Sec-01B VIP Special 1
Sec-01B VIP CourtsideSeatView 2
有没有一种快速的方法可以做到这一点并将其加载到临时 table 中,并在 SQL 服务器中使用一些奇特的非游标 T-SQL?
如果是一次性工作,请尝试 UNPIVOT to convert the SubSectionId..N columns into rows. Then add a ROW_NUMBER() 结果以按部分和小节生成订单号
-- Unpivot the table.
SELECT unpvt.SectionId
, unpvt.Description
, unpvt.SubSection
, ROW_NUMBER() OVER(PARTITION BY SectionId ORDER BY SubSection) AS RowOrder
FROM
( SELECT SectionId
, Description
, SubSectionIdA
, SubSectionIdB
, SubSectionIdC
, SubSectionIdD
, SubSectionIdE
FROM Sections
) p
UNPIVOT
(
SubSection FOR SubSectionId
IN (SubSectionIdA
, SubSectionIdB
, SubSectionIdC
, SubSectionIdD
, SubSectionIdE
)
)AS unpvt
WHERE ISNULL(SubSection, '') <> ''
结果:
SectionId | Description | SubSection | RowOrder :-------- | :-------------- | :---------------- | -------: Sec-01A | Special section | SubsectionA1 | 1 Sec-01A | Special section | SubsectionA2 | 2 Sec-01B | VIP | CourtsideSeatView | 1 Sec-01B | VIP | Special | 2 Sec-02B | Cheap seats | CheapSeciton1 | 1 Sec-02B | Cheap seats | CheapSectionTop | 2 Sec-02B | Cheap seats | LimitedView | 3
另见 db<>fiddle