【问题标题】:Is it possible to pivot on two columns? (if that's even the correct way to ask this?)是否可以在两列上旋转? (如果这是问这个问题的正确方法吗?)
【发布时间】:2016-04-18 13:26:02
【问题描述】:

我正在尝试创建一个以可读格式打印我们的家庭房间数量的报告。我们目前有一个手动填写的 Excel 模板,但我想在 SQL 中自动化这个过程,这样我们就可以从数据库中提取报告。由于这是公立学校数据,我不会发布我的子查询或“真实”数据,但我会尽可能具体。

我有一个子查询,它提取我命名为 Data 的 student_ID、School_Title、Grade_Level 和 HomeRoom。出于本次讨论的目的,我们假设 Data 实际上是我数据库中的一个表。我一直在研究使用支点,但它似乎并没有满足我的需要。我们有多所学校,每所学校每个年级都有多个班主任。每所学校的每个年级都有不同数量的班主任,具体取决于学校的规模。 (所以学校 1 可能只有 2 个幼儿园班,但 School4 可能有 4 个幼儿园班)。

数据如下所示:

Student_ID     School_Title    Grade_Level    HomeRoom
12345          School1         KA             HR1
23456          School1         KP             HR2
34567          School1         01             HR3
45678          School1         01             HR4
......
56789          School7         06             HR100

我现在使用的查询是(在 SQL Server 2012 中):

SELECT *
FROM Data
PIVOT (Count(student_ID)
   FOR GRADE_LEVEL IN ([KA],[KP],[01],[02],[03],[04],[05],[06])
   ) as PivotStudents
ORDER BY School_Title

但我得到的是:

School_Title   HomeRoom   KA   KP   01   02   03   04   05   06
School 1       HR1        25   0    0    0    0    0    0    0
School 1       HR2        0    26   0    0    0    0    0    0
School 1       HR3        0    0    19   0    0    0    0    0
School 1       HR4        0    0    21   0    0    0    0    0
....
School 7       HR100      0    0    0    0    0    0    0    27

我想出来的是:

School_Title   HR   KA   HR   KP   HR   01  HR   02...
School 1       HR1  25   HR2  26   HR3  19  HR5  23
School 1                           HR4  21
...
School 7       HR91 19   HR92 19   HR93 20  HR98 21
School 7       HR94 17   HR95 23   HR96 18  HR99 24
School 7                           HR97 22

我不在乎哪些是“连续”组合在一起的。因此,在我的脑海中,HR3 恰好是找到的第一个 01 年级班主任,所以它在第 1 行。但是 HR4 也是第 1 学校的 01 年级班主任,并且是下一个找到的,所以它进入第 2 行。

一个班也可能有多个年级(虽然只有两种情况,但我需要考虑到这是可能的)。

所以基本上,我想要的输出在 SQL 中是否可行?我是否需要从数据库中取出 Crystal 或其他东西才能将数据“放置”到我想要的位置,或者我是否可以为 SQL 提供足够的信息来按照我的意愿对其进行格式化。

谢谢! 数据库

【问题讨论】:

  • 我不确定我是否正确理解了您的要求。无论顺序如何,您都希望它们在同一行中?或者你到底想要什么?
  • 基本上我想摆脱很多零显示:) 因此,在第一个表(使用我当前的 SQL)中,每个教室都是一行,并显示每个年级的学生人数。而在第二张表(我想要的理想)中,它列出了每个年级找到的第一个班主任。因此,为该年级找到的第一个班主任(按班主任名称的 alpha 排序就可以了)显示在第 1 行的那个年级列中,而该年级的第二个班主任显示在第 2 行的那个年级列中...
  • 所以基本上每所学校一条线可以做到吗?如果是这样,您应该尝试GROUP BY School_Title
  • 我希望!如果每所学校的每个年级只有一个班主任,我会选择按组上课和按顺序上课,而根本不会搞乱支点。老实说,我开始认为我正在尝试做的事情仅在 SQL 中是不可能的......
  • 哦,好的,我明白了。能否举个例子说明Data 表是如何构造的?

标签: sql-server-2012 pivot


【解决方案1】:

您可以使用带有案例语句的聚合来做到这一点。关键是在您的数据中添加一个 DENSE_RANK 列,以将聚合分成行。

SELECT
    [School_Title],
    [HR] = MAX(CASE WHEN [Grade_Level] = 'KA' THEN [HomeRoom] END),
    [KA] = COUNT(CASE WHEN [Grade_Level] = 'KA' THEN [Student_ID] END),
    [HR] = MAX(CASE WHEN [Grade_Level] = 'KP' THEN [HomeRoom] END),
    [KP] = COUNT(CASE WHEN [Grade_Level] = 'KP' THEN [Student_ID] END),
    [HR] = MAX(CASE WHEN [Grade_Level] = '01' THEN [HomeRoom] END),
    [01] = COUNT(CASE WHEN [Grade_Level] = '01' THEN [Student_ID] END)
    -- etc
FROM
    (
        SELECT  *,
                DENSE_RANK() OVER (PARTITION BY [School_Title], [Grade_Level] ORDER BY [HomeRoom]) Rn
        FROM    [Data]
    ) d
GROUP BY [School_Title], [RN]

SQL FIDDLE

【讨论】:

  • 谢谢!现在尝试修改:)
  • Hrm,这让我比我尝试 PIVOT 时更接近,但仍然不完全。这似乎只让我每所学校有一排,所以它抓住了适合这种情况的每栋建筑物的顶级教室。因此,如果我们在第 1 学校有 4 个 KA 班主任,那么它只会选择顶级班主任。但它确实列出了学校,然后是 KA 的 HR1 名称,然后是 KA 的 HR1 计数,然后是 KP 的 HR2 名称,然后是 KP 的 HR2 计数,依此类推。我假设它是这样做的“MAX”......
  • 这样做的唯一方法是,如果您没有在我的答案中包含 ROW_NUMBER() OVER (PARTITION BY [School_Title], [Grade_Level] ORDER BY [HomeRoom]),或者您没有使用 GROUP BY Rn
  • 你说得对,我已经取消了 Rn 的小组,因为它没有计算实际的学生并且正在摆弄它!无论如何,我使用了您对 case 语句和最大值的想法,并且只是在子查询中进行了计数,这样我就不必在 case 语句中搞砸了。像魅力一样工作!
  • @DianneBates 我明白你在说什么。实际上只需将我的查询更改为 DENSE_RANK() 而不是 ROW_NUMBER() 也可以解决这个问题
【解决方案2】:

Jamie 与上述类似,但将 Count 更改为与 Data Subquery 一起发生,并将 Max 用于所有 case 语句,所以......

Select
   School_Title,
   [HR1]=MAX(CASE WHEN [grade_level]='KA' THEN [HomeRoom] END),
   [KA]=MAX(CASE WHEN [grade_level]='KA' THEN [Number] END),
   [HR2]=MAX(CASE WHEN [grade_level]='KP' THEN [HomeRoom] END),
   [KP]=MAX(CASE WHEN [grade_level]='KP' THEN [Number] END),
   ..... etc.
From (
   select *, ROW_NUMBER() OVER (PARTITION BY School_Title, Grade_LEvel ORDER by HomeRoom) Rn
   from (
      select count(student_id) as Number, School_Title, Grade_Level, HomeRoom
      from Data
      group by School_Title, Grade_Level, HomeRoom) data2
GROUP BY School_Title, Rn
ORDER BY SCHOOL_Title

我需要在沿线的某处添加一些 IsNull,这样一所拥有 4 个 1 年级班主任但只有 3 个 2 年级班主任的学校就不会在该学校的最后一行有 NULL/NULL 冷却,而是全部在总之,我不敢相信这真的可以用 SQL 完成!!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2021-06-10
    • 2011-11-23
    相关资源
    最近更新 更多