将所有行显示为两列

时间:2015-10-30 11:28:20

标签: postgresql

我有这样的观点。

SemesterId  Course     Grade
1           course1     A
1           course2     B
1           course3     C
2           course4     D
2           course5     A
2           course6     B
2           course7     C
3           course8     D
3           course9     A
3           course10    B
4           course11    C
4           course12    D

我希望使用postgre SQL获得如下结果。

SemesterId1 Course1 Grade1  SemesterId2 Course2  Grade2
1           course1  A             2    course4   D
1           course2  B             2    course5   A
1           course3  C             2    course6   B
                                   2    course7   C
3           course8  D             4    course11  C
3           course9  A             4    course12  D
3           course10 B          

我怎样才能得到这个结果?

2 个答案:

答案 0 :(得分:0)

我不知道你为什么这样做,但你可以使用:

WITH tab_row_num AS (
    SELECT row_number() over (PARTITION BY "SemesterId") rn, "SemesterId" , "Course" , "Grade" FROM table1
),
joint_tab AS (
select
    t1_3."SemesterId" AS "SemesterId1", t1_3."Course" as "Course1" , t1_3."Grade" as "Grade1",
    t2_4."SemesterId" AS "SemesterId2", t2_4."Course" as "Course2" , t2_4."Grade" as "Grade2"
from tab_row_num t1_3
    full outer join tab_row_num t2_4
        ON (t1_3."SemesterId" = 1 AND t2_4."SemesterId"=2 AND t1_3.rn=t2_4.rn)
            OR (t1_3."SemesterId" = 3 AND t2_4."SemesterId"=4 AND t1_3.rn=t2_4.rn) 
)
SELECT 
    COALESCE("SemesterId1"::TEXT, '') , COALESCE("Course1"::TEXT, '') , COALESCE("Grade1"::TEXT, ''),
    COALESCE("SemesterId2"::TEXT, '') , COALESCE("Course2"::TEXT, '') , COALESCE("Grade2"::TEXT, '')
FROM (
    SELECT *
    FROM (
        SELECT "SemesterId1" , "Course1" , "Grade1", "SemesterId2" , "Course2" , "Grade2"
        FROM joint_tab t
        WHERE (t."SemesterId1" = 1 OR t."SemesterId1" IS NULL) AND (t."SemesterId2" = 2 OR t."SemesterId2" IS NULL)
        ORDER BY "SemesterId1" NULLS LAST, "Course1" ASC, "Grade1" ASC, "SemesterId2" NULLS LAST, "Course2" ASC, "Grade2" ASC
    ) sub1
    UNION ALL

    SELECT * FROM (
        SELECT "SemesterId1" , "Course1" , "Grade1", "SemesterId2" , "Course2" , "Grade2"
        FROM joint_tab t WHERE (t."SemesterId1" = 3 OR t."SemesterId1" IS NULL) AND (t."SemesterId2" = 4 OR t."SemesterId2" IS NULL)
        ORDER BY "SemesterId1" NULLS LAST, "Course1" ASC, "Grade1" ASC, "SemesterId2" NULLS LAST, "Course2" ASC, "Grade2" ASC
    ) sub2
) sub

答案 1 :(得分:0)

这种任务应该在客户端解决。但是,它也是SQL中需要解决的一个有趣问题。

select 
    sid1, course1, grade1,
    sid2, course2, grade2
from (
    select 
        c1.semesterid sid1, c1.course course1, c1.grade grade1, c1.rk, c1.rn,
        c2.semesterid sid2, c2.course course2, c2.grade grade2, c2.rk, c2.rn
    from (
        select *, dense_rank() over w rk, row_number() over w rn
        from courses
        where semesterid % 2 = 1
        window w as (order by semesterid)
        ) c1
    full join ( 
        select *, dense_rank() over w rk, row_number() over w rn
        from courses
        where semesterid % 2 = 0
        window w as (order by semesterid)
        ) c2
    on c1.rk = c2.rk and c1.rn = c2.rn
    order by coalesce(c1.rk, c2.rk), coalesce(c1.rn, c2.rn)
    ) sub

 sid1 | course1  | grade1 | sid2 | course2  | grade2 
------+----------+--------+------+----------+--------
    1 | course1  | A      |    2 | course4  | D
    1 | course2  | B      |    2 | course5  | A
    1 | course3  | C      |    2 | course6  | B
      |          |        |    2 | course7  | C
    3 | course8  | D      |      |          | 
    3 | course9  | A      |    4 | course11 | C
    3 | course10 | B      |    4 | course12 | D
(7 rows)