使用SQL为其余列创建列值标头

时间:2012-10-19 22:37:58

标签: tsql group-by

我有下表

ID | Group      | Type         | Product
1    Dairy         Milk           Fresh Milk
2    Dairy         Butter         Butter Cream
3    Beverage      Coke           Coca cola
4    Beverage      Diet           Dew
5    Beverage      Juice          Fresh Juice

我需要以下输出/查询结果:

ID | Group      | Type         | Product
1    Dairy             
1                 Milk           Fresh Milk
2                 Butter         Butter Cream
2    Beverage      
1                Coke            Coca cola
2                Diet            Dew
3                Juice           Fresh Juice

对于上面的示例,硬编码脚本可以完成这项工作,但我会为任意数量的组寻找动态脚本。我不知道如何做到这一点,我还没有样例查询。我需要想法,至少给我一个想法的例子。 PIVOT看起来很接近但看起来并不完全适合这种情况。

3 个答案:

答案 0 :(得分:2)

这是一种可行的方法。它基本上将“Group-Headers”和“Group-Items”联合起来。困难在于正确地订购它们。

WITH CTE AS
(
  SELECT ID,[Group],Type,Product,
    ROW_NUMBER() OVER (PARTITION BY [Group] Order By ID)AS RN
  FROM Drink
)
SELECT ID,[Group],Type,Product
FROM(
   SELECT RN AS ID,[Group],[Id]AS OriginalId,'' As Type,'' As Product, 0 AS RN, 'Group' As RowType
   FROM CTE WHERE RN = 1
   UNION ALL
   SELECT RN AS ID,'' AS [Group],[Id]AS OriginalId,Type,Product, RN, 'Item' As RowType
   FROM CTE
)X
ORDER BY  OriginalId ASC
, CASE WHEN RowType='Group' THEN 0 ELSE 1 END ASC
, RN ASC

这是一个演示小提琴:http://sqlfiddle.com/#!6/ed6ca/2/0

答案 1 :(得分:2)

略微简化的方法:

With Groups As
    (
    Select Distinct Min(Id) As Id, [Group], '' As [Type], '' As Product
    From dbo.Source
    Group By [Group]
    )
Select Coalesce(Cast(Z.Id As varchar(10)),'') As Id
  , Coalesce(Z.[Group],'') As [Group]
  , Z.[Type], Z.Product
From    (
        Select Id As Sort, Id, [Group], [Type], Product
        From Groups
        Union All
        Select G.Id, Null, Null, S.[Type], S.Product
        From dbo.Source As S
            Join Groups As G
                On G.[Group] = S.[Group]
        ) As Z
Order By Sort

应该注意的是Coalesce的使用纯粹是出于美学原因。在这些情况下,您只需返回null。

SQL Fiddle

答案 2 :(得分:0)

采用ROW_NUMBER的方法:

IF OBJECT_ID('dbo.grouprows') IS NOT NULL DROP TABLE dbo.grouprows;

CREATE TABLE dbo.grouprows(
ID INT,
 Grp NVARCHAR(MAX),
 Type NVARCHAR(MAX),
 Product NVARCHAR(MAX)
 );
 INSERT INTO dbo.grouprows VALUES
(1,'Dairy','Milk','Fresh Milk'),
(2,'Dairy','Butter','Butter Cream'),
(3,'Beverage','Coke','Coca cola'),
(4,'Beverage','Diet','Dew'),
(5,'Beverage','Juice','Fresh Juice');

SELECT 
CASE WHEN gg = 0 THEN dr1 END GrpId,
CASE WHEN gg = 1 THEN rn1 END TypeId,
ISNULL(Grp,'')Grp,
CASE WHEN gg = 1 THEN Type ELSE '' END Type,
CASE WHEN gg = 1 THEN Product ELSE '' END Product
FROM(
SELECT *,
DENSE_RANK()OVER(ORDER BY Grp DESC) dr1
FROM( 
SELECT *,
ROW_NUMBER()OVER(PARTITION BY Grp ORDER BY type,gg) rn1,
ROW_NUMBER()OVER(ORDER BY type,gg) rn0
FROM(
SELECT  Grp,Type,Product, GROUPING(Grp) gg, GROUPING(type) tg FROM dbo.grouprows
GROUP BY Product, Type, Grp
WITH ROLLUP
)X1
WHERE tg = 0
)X2
WHERE gg=1 OR rn1 = 1
)X3
ORDER BY rn0