在复杂的 Select 语句中将列显示为行 - sql

Displaying columns as rows in a complex Select statement - sql

我有两个 table(一个基础 table 和一个数据 table),我正在使用 OUTER APPLY 合并它们以获得结果。

tblBase 看起来像这样:

+------+------+
| IDnu | Name |
+------+------+
|  1   | abc  |
|  2   | cde  |
|  3   | efg  |
|  4   | rfl  |
+------+------+

tblData是这样的:

+------+--------+--------+--------+-------------+
| IDNu | Price1 | Price2 | Price3 | ProductType |
+------+--------+--------+--------+-------------+
|    1 |     10 |     15 |     20 | Old         |
|    2 |     10 |     20 |     30 | Refurbished |
|    3 |     20 |     30 |     40 | New         |
|    1 |     20 |     15 |     20 | New         |
|    2 |     20 |     10 |     30 | Old         |
+------+--------+--------+--------+-------------+

我当前根据几个条件计算 tblData 的查询如下:

Select IDNu, Name, t2.PNew, t2.POld FROM tblBase as t1
OUTER APPLY
(
SELECT
  SUM (CASE WHEN ProductType = 'New' THEN Price1 + Price2 ELSE 0 END) AS PNew, 
  SUM (CASE WHEN ProductType = 'Old' THEN Price2 + Price3 ELSE 0 END) AS POld
FROM tblData
WHERE IDNu = t1.IDNu
GROUP BY IDNu
) t2

以上查询结果为:

+------+------------+------+------+
| IDNu |    Name    | PNew | POld |
+------+------------+------+------+
|    1 | abc        | 35   | 35   |
|    2 | cde        | 0    | 40   |
|    3 | efg        | 50   | 0    |
|    4 | rfl        | NULL | NULL |
+------+------------+------+------+

现在我的问题是,不是在两列中显示 PNew 和 Pold,而是在行中显示它们? 像这样:

+------+------------+-------------+-------+
| IDNu |    Name    | ProductType | Price |
+------+------------+-------------+-------+
|    1 | abc        | PNew        | 35    |
|    2 | cde        | PNew        | 0     |
|    3 | efg        | PNew        | 50    |
|    4 | rfl        | PNew        | NULL  |
|    1 | abc        | POld        | 35    |
|    2 | cde        | POld        | 40    |
|    3 | efg        | POld        | 0     |
|    4 | rfl        | POld        | NULL  |
+------+------------+-------------+-------+
select b.IDNu, b.Name, pt.ProductType, d.Price
from
    tblBase as b cross join (select 'New' ProductType union all select 'Old') pt
    left outer join
    (
        select
            ProductType,
            sum(case ProductType
                    when 'New' then Price1 + Price2
                    when 'Old' then Price2 + Price3 end) as Price
        from tblData
        where ProductType in ('New', 'Old') /* not strictly necessary but maybe faster */
        group by IDNu, ProductType
    ) d
        on d.IDNu = p.IDNu and d.ProductType = pt.ProductType
order by b.IDNu, pt.ProductType

或...

select
    b.IDNu, b.Name, pt.ProductType,
    sum(case pt.ProductType
            when 'New' then d.Price1 + d.Price2
            when 'Old' then d.Price2 + d.Price3 end) as Price
from
    tblBase as b
    cross join
    (select 'New' ProductType union all select 'Old') pt
    left outer join
    tblData d on d.IDNu = p.IDNu and d.ProductType = pt.ProductType
group by b.IDNu, pt.ProductType
order by b.IDNu, pt.ProductType

在您的输出中,您在没有数据的地方混合了一些零和空输出。当然,翻译这些空值的正常方法是使用 coalesce()。你也有 "PNew" 和 "POld" 作为你的输出值,但我不确定这是故意的。一个简单的 case 将处理输出 select 子句中的那些。

你能试试这个吗:

SELECT tblBase.*, 'PNew' as ProductType, tblData.Price1 + tblData.Price2 as Price
 FROM tblBase left join `tblData`
 On tblBase.IDnu = tblData.IDnu AND tblData.ProductType = 'New' 
UNION ALL
SELECT tblBase.*, 'POld' as ProductType, tblData.Price3 + tblData.Price2 as Price
 FROM tblBase left join `tblData`
 On tblBase.IDnu = tblData.IDnu AND tblData.ProductType = 'Old' 

最简单的方法是在应用的外部旋转 table:

Select 
    IDNu,Name,t2.ProductType,t2.Price
FROM 
    tblBase as t1
    OUTER APPLY (
        SELECT ProductType='New',SUM(Price1+Price2) AS Price
        FROM tblData
        WHERE IDNu=t1.IDNu AND ProductType='New'
        UNION ALL
        SELECT ProductType='Old',SUM(Price2+Price3) AS Price
        FROM tblData
        WHERE IDNu=t1.IDNu AND ProductType='Old'
    ) t2