SQL 多字段反旋转
SQL multiple field un-pivoting
我有如下数据
CREATE TABLE #TEMP(OrderId int, Country varchar(100),Area varchar(100),Hotel varchar(100),CountryDetail varchar(100),AreaDetail varchar(100),HotelDetail varchar(100))
INSERT INTO #TEMP
VALUES(1,'Bhutan','Thimphu','Taj Tashi','Bhutan country info','Thimphu area info','Taj Tashi hotel info'),
(2,'Bhutan','Punakha','COMO Uma Punakha','Bhutan country info','Punakha area info','COMO Uma Punakha hotel info'),
(3,'Bhutan','Punakha','COMO Uma Paro','Bhutan country info','Punakha area info','COMO Uma Paro hotel info')
我想要的预期输出
Item ItemDetail OrderId
Bhutan Bhutan country info 1
Thimphu Thimphu area info 1
Taj Tashi Taj Tashi hotel info 1
Punakha Punakha area info 2
COMO Uma Punakha COMO Uma Punakha hotel info 2
COMO Uma Paro COMO Uma Paro hotel info 3
输出是基于不重复国家、地区或酒店,按orderid只显示一次
目前已尝试
;WITH CTE AS (SELECT OrderId,Country,Area,Hotel,CountryDetail,AreaDetail,HotelDetail,
CountryDupe = ROW_NUMBER() OVER (PARTITION BY Country ORDER BY OrderId),
AreaDupe = ROW_NUMBER() OVER (PARTITION BY Area ORDER BY OrderId),
HotelDupe = ROW_NUMBER() OVER (PARTITION BY Hotel ORDER BY OrderId)
from #TEMP)
SELECT ITEM, OrderId
FROM (SELECT OrderId,CountryDetail,
CASE WHEN CountryDupe=1 THEN Country ELSE '' END AS Country,
CASE WHEN AreaDupe = 1 THEN Area ELSE '' END AS Area,
CASE WHEN HotelDupe = 1 THEN Hotel ELSE '' END AS Hotel
FROM CTE) P
UNPIVOT(
ITEM
FOR ITEMS IN (Country,Area,Hotel)
) UNPVT
WHERE LEN(ITEM)>1
ORDER BY OrderId
不确定如何在此处提取相关项目详细信息。
SQL FIDDLE here
您想对数据进行逆透视。我推荐 cross apply
:
select t.orderid, v.item, v.itemdetail
from temp t cross apply
(values (country, countrydetail),
(hotel, hoteldetail)
) v(item, itemdetail);
Here 是一个 db<>fiddle.
这是一些奇怪的逻辑,但是,您可以使用 table 构造函数 VALUES
来逆透视数据,然后 ROW_NUMBER
仅 return "first"订单:
WITH RNs AS(
SELECT V.Item,
V.ItemDetail,
T.OrderId,
ROW_NUMBER() OVER (PARTITION BY V.Item, V.ItemDetail ORDER BY T.OrderId ASC) AS RN
FROM #TEMP T
CROSS APPLY (VALUES(T.Country, T.CountryDetail),
(T.Area, T.AreaDetail),
(T.Hotel, T.HotelDetail))V(Item, ItemDetail))
SELECT RNs.Item,
RNs.ItemDetail,
RNs.OrderId
FROM RNs
WHERE RN = 1
ORDER BY RNs.OrderId ASC;
我有如下数据
CREATE TABLE #TEMP(OrderId int, Country varchar(100),Area varchar(100),Hotel varchar(100),CountryDetail varchar(100),AreaDetail varchar(100),HotelDetail varchar(100))
INSERT INTO #TEMP
VALUES(1,'Bhutan','Thimphu','Taj Tashi','Bhutan country info','Thimphu area info','Taj Tashi hotel info'),
(2,'Bhutan','Punakha','COMO Uma Punakha','Bhutan country info','Punakha area info','COMO Uma Punakha hotel info'),
(3,'Bhutan','Punakha','COMO Uma Paro','Bhutan country info','Punakha area info','COMO Uma Paro hotel info')
我想要的预期输出
Item ItemDetail OrderId
Bhutan Bhutan country info 1
Thimphu Thimphu area info 1
Taj Tashi Taj Tashi hotel info 1
Punakha Punakha area info 2
COMO Uma Punakha COMO Uma Punakha hotel info 2
COMO Uma Paro COMO Uma Paro hotel info 3
输出是基于不重复国家、地区或酒店,按orderid只显示一次
目前已尝试
;WITH CTE AS (SELECT OrderId,Country,Area,Hotel,CountryDetail,AreaDetail,HotelDetail,
CountryDupe = ROW_NUMBER() OVER (PARTITION BY Country ORDER BY OrderId),
AreaDupe = ROW_NUMBER() OVER (PARTITION BY Area ORDER BY OrderId),
HotelDupe = ROW_NUMBER() OVER (PARTITION BY Hotel ORDER BY OrderId)
from #TEMP)
SELECT ITEM, OrderId
FROM (SELECT OrderId,CountryDetail,
CASE WHEN CountryDupe=1 THEN Country ELSE '' END AS Country,
CASE WHEN AreaDupe = 1 THEN Area ELSE '' END AS Area,
CASE WHEN HotelDupe = 1 THEN Hotel ELSE '' END AS Hotel
FROM CTE) P
UNPIVOT(
ITEM
FOR ITEMS IN (Country,Area,Hotel)
) UNPVT
WHERE LEN(ITEM)>1
ORDER BY OrderId
不确定如何在此处提取相关项目详细信息。
SQL FIDDLE here
您想对数据进行逆透视。我推荐 cross apply
:
select t.orderid, v.item, v.itemdetail
from temp t cross apply
(values (country, countrydetail),
(hotel, hoteldetail)
) v(item, itemdetail);
Here 是一个 db<>fiddle.
这是一些奇怪的逻辑,但是,您可以使用 table 构造函数 VALUES
来逆透视数据,然后 ROW_NUMBER
仅 return "first"订单:
WITH RNs AS(
SELECT V.Item,
V.ItemDetail,
T.OrderId,
ROW_NUMBER() OVER (PARTITION BY V.Item, V.ItemDetail ORDER BY T.OrderId ASC) AS RN
FROM #TEMP T
CROSS APPLY (VALUES(T.Country, T.CountryDetail),
(T.Area, T.AreaDetail),
(T.Hotel, T.HotelDetail))V(Item, ItemDetail))
SELECT RNs.Item,
RNs.ItemDetail,
RNs.OrderId
FROM RNs
WHERE RN = 1
ORDER BY RNs.OrderId ASC;