一行中有多行

时间:2013-07-17 13:47:10

标签: tsql jpa

所以我有一张表,看起来像这样:

ID  |  parentID  |   name   |  typeID
---------------------------------------
1   |      2     |  thing1  |    1
2   |      4     |  region1 |    0
3   |      4     |  region2 |    0
4   |     NULL   |  region3 |    0
5   |      3     |  foo1    |    2
5   |      3     |  foo2    |    2
6   |      3     |  bar1    |    3

我需要的是一个像这样的输出:

ID  |  region  |   thing  |  foo  |  bar
--------------------------------------------
1   |  region1 |  thing1  |  NULL |  NULL
2   |  region2 |  NULL    |  foo1 |  bar1
3   |  region2 |  NULL    |  foo2 |  NULL
4   |  region3 |  NULL    |  NULL |  NULL

有了这个

Select ID,
    (CASE WHEN [typeID] = 0 THEN [name] END) AS region,
    (CASE WHEN [typeID] = 1 THEN [name] END) AS thing,
    (CASE WHEN [typeID] = 3 THEN [name] END) AS foo,
    (CASE WHEN [typeID] = 5 THEN [name] END) AS bar
FROM [my].[dbo].[foobarthingtable]
where type = 0 OR type = 1 OR type = 3 OR type = 5 

我得到这个(逻辑上):

ID  |  region  |   thing  |  foo  |  bar
--------------------------------------------
1   |  NULL    |  thing1  |  NULL |  NULL
2   |  region1 |  NULL    |  NULL |  NULL
3   |  region2 |  NULL    |  NULL |  NULL
4   |  region3 |  NULL    |  NULL |  NULL
5   |  NULL    |  NULL    |  foo1 |  NULL
6   |  NULL    |  NULL    |  foo2 |  NULL
7   |  NULL    |  NULL    |  NULL |  bar1

如何在(父)区域的同一行中获得那些“foos”,“bars”和“things”? JPA方式(CriteriaQuery)也很不错,因为我必须在JSF页面上将其显示为概述。

THX

3 个答案:

答案 0 :(得分:1)

现在您应该按ID

设置GROUP结果

SQLFiddle demo

WITH CTE AS
(
Select 

    (case when [typeID]=0 then ID ELSE parentID END) as ID,


    (CASE WHEN [typeID] = 0 THEN [name] END) AS region,
    (CASE WHEN [typeID] = 1 THEN [name] END) AS thing,
    (CASE WHEN [typeID] = 3 THEN [name] END) AS bar,
    (CASE WHEN [typeID] = 2 THEN [name] END) AS foo
FROM foobarthingtable
where typeid in (0,1,3,2)
)

select id,
 MAX(REGION) REGION,
 MAX(THING) THING,
 MAX(FOO) FOO,
 MAX(BAR) BAR 
from CTE group by id

答案 1 :(得分:1)

您可以尝试使用PIVOT声明

;WITH PivotData AS
(
SELECT
    ISNULL(t2.name, t1.name) as ParentRegion, -- grouping column
    t1.name, -- aggregation column
    CASE t1.typeid
       WHEN 1 THEN 'thing'
       WHEN 2 THEN 'foo'
       WHEN 3 THEN 'bar'
    END as mycolumn -- spreading column
FROM foobarthingtable t1
LEFT JOIN foobarthingtable t2 ON t1.[parentID]=t2.id AND t2.typeID = 0
WHERE t1.typeID in (0,1,2,3,5)
)
SELECT ParentRegion, [thing], [foo], [bar]
FROM PivotData
PIVOT(MAX(name) FOR mycolumn IN ([thing], [foo], [bar]) ) AS P
ORDER BY ParentRegion;

答案 2 :(得分:1)

最后,我知道了

;With NumberSequence( Number ) as
(
    Select 1 as Number
        union all
    Select Number + 1
        from NumberSequence
        where Number < 100
),
base_list AS (
    SELECT
       ISNULL(t2.name, t1.name) as Region,
       t1.name,
       t1.typeid
    FROM foobarthingtable t1
    LEFT JOIN foobarthingtable t2 ON t1.[parentID]=t2.id AND t2.typeID = 0
)
SELECT
    ROW_NUMBER() OVER (ORDER BY reg_list.Region, reg_list.Number) as ID,
    reg_list.Region AS region,
    thing_list.name AS thing,
    foo_list.name AS foo,
    bar_list.name AS bar
FROM (
    SELECT
       t1.Region,
       NumberSequence.Number
    FROM (
       SELECT DISTINCT 
          ISNULL(t2.name, t1.name) as Region
       FROM foobarthingtable t1
       LEFT JOIN foobarthingtable t2 ON t1.[parentID]=t2.id AND t2.typeID = 0
       WHERE t1.typeID in (0,1,2,3,5)
    ) t1
    CROSS JOIN NumberSequence
) as reg_list

LEFT JOIN (
    SELECT
       bl.Region, bl.name, ROW_NUMBER() OVER(ORDER BY bl.Region, bl.name) rn
    FROM base_list bl
    WHERE typeID =1
) thing_list ON thing_list.Region=reg_list.Region AND reg_list.number=thing_list.rn

LEFT JOIN (
    SELECT
       bl.Region, bl.name, ROW_NUMBER() OVER(ORDER BY bl.Region, bl.name) rn
    FROM base_list bl
    WHERE typeID =2
) foo_list ON foo_list.Region=reg_list.Region AND reg_list.number=foo_list.rn

LEFT JOIN (
    SELECT
       bl.Region, bl.name, ROW_NUMBER() OVER(ORDER BY bl.Region, bl.name) rn
    FROM base_list bl
    WHERE typeID =3
) bar_list ON bar_list.Region=reg_list.Region AND reg_list.number=bar_list.rn

WHERE thing_list.name is not null or foo_list.name IS NOT NULL OR bar_list.name IS NOT NULL OR  reg_list.Number=1

ORDER BY     reg_list.Region,    reg_list.Number