【问题标题】:SQL multiple field un-pivotingSQL 多字段反透视
【发布时间】:2020-03-04 13:00:10
【问题描述】:

我有如下数据

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

【问题讨论】:

  • 为什么订单2只有2行,订单3只有1行?

标签: sql sql-server pivot sql-server-2016 unpivot


【解决方案1】:

这是一些奇怪的逻辑,但是,您可以使用表构造函数 VALUES 取消透视数据,然后 ROW_NUMBER 只返回“第一”顺序:

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;

【讨论】:

  • 。 . .你需要ASC
【解决方案2】:

您想要取消透视数据。我推荐cross apply

select t.orderid, v.item, v.itemdetail
from temp t cross apply
     (values (country, countrydetail),
             (hotel, hoteldetail)
     ) v(item, itemdetail);

Here 是一个 dbfiddle。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-23
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多