分组依据创建重复行

Posted

技术标签:

【中文标题】分组依据创建重复行【英文标题】:Group By Creates Duplicate Rows 【发布时间】:2018-09-22 11:11:00 【问题描述】:

我正在使用Oracle sql 创建示例数据 GridView 并遇到了一个非常基本的问题。所以在这里,我必须按月组织数据,根据状态列说一个月内没有员工。所以状态 = 0; Jan1 和状态 > 0; 1 月 2 日。我没有详细说明任何其他内容,因为它已经有一个内置视图,这就是我必须用来让它工作的东西。因此,这是我正在使用的查询和运行良好的示例输出,除了一个:

SELECT DISTINCT SYEAR, DEPT_NAME,

--Month-wise data - Starts
DECODE ( upper((MONTHNAMESHORT)), 'JAN', NVL((FirstLetter), 0), NULL) "JAN1" ,  
DECODE ( upper((MONTHNAMESHORT)), 'JAN', NVL((SecondLetter), 0), NULL) "JAN2",
DECODE ( upper((MONTHNAMESHORT)), 'FEB', NVL((FirstLetter), 0), NULL) "FEB1" ,  
DECODE ( upper((MONTHNAMESHORT)), 'FEB', NVL((SecondLetter), 0), NULL) "FEB2"
--Month-wise data - Ends

FROM

--Sub-query - starts
(SELECT DISTINCT VWWEBLETTERSTATUS2.SYEAR, MONTHRANK.MONTHNAMESHORT,VWWEBLETTERSTATUS2.DEPT_NAME,
  nvl(fnfirstletter(DEPT_NAME,upper(MONTHRANK.MONTHNAMESHORT),VWWEBLETTERSTATUS2.SYEAR),0) FirstLetter,
  nvl(fnSecondLetter(DEPT_NAME,upper(MONTHRANK.MONTHNAMESHORT),VWWEBLETTERSTATUS2.SYEAR),0) SecondLetter,MONTHRANK.RANK  
  FROM
MONTHRANK,VWWEBLETTERSTATUS2 where VWWEBLETTERSTATUS2.SYEAR = '2018' AND
  nvl(fnfirstletter(DEPT_NAME,upper(MONTHRANK.MONTHNAMESHORT),VWWEBLETTERSTATUS2.SYEAR), 0) <> 0 AND
  nvl(fnSecondLetter(DEPT_NAME,upper(MONTHRANK.MONTHNAMESHORT),VWWEBLETTERSTATUS2.SYEAR), 0) <> 0
order by DEPT_NAME, rank) q
--Sub-query - Ends

GROUP BY SYEAR, (MONTHNAMESHORT), DEPT_NAME; --Issue here - For the month-wise group by

输出

Year    Dept    Jan1 Jan2 Feb1 Feb2
2018    UNIT-I3 93   87             
2018    UNIT-I5 62   66
2018    QA      0    0      
2018    UNIT-I5           87   66

对于GROUP BY (MONTHNAMESHORT) 子句,它会为部门和特定年份创建重复行。假设当 Unit-I5 有两个月的数据时,它会创建单独的行,尽管它应该在一行中。 有什么办法可以克服保持相同的问题,只是GROUP BY 的替代品?

更新 1:甚至尝试过这个,但没有用

SUM(CASE WHEN Q.MONTHNAMESHORT = 'JAN' THEN Q.FirstLetter ELSE 0 END) "JAN1",
SUM(CASE WHEN Q.MONTHNAMESHORT = 'JAN' THEN Q.SecondLetter ELSE 0 END) "JAN2"

注意:FirstLetter 和 SecondLetter 计入视图。

【问题讨论】:

您的信息不完整。请包括 MONTHRANK 和 VWWEBLETTERSTATUS2 的行数据。并包含 fnfirstletter 功能 GROUP BY ___ 的意思是“给我一个结果行每个___”。因此,对于您的GROUP BY 子句,您说您想要每个年月部门的结果行,但您真正想要的是每个年部门的一行(因为再过一个月,您不想要另一行;您想要几个月而是在列中)。 当您研究 Gordon 的答案时,如果您想了解更多有关该技术(称为“条件聚合”)的信息,它可能会帮助您了解您在问题中需要的操作类型是称为旋转。使用谷歌研究这个概念——特别是,你会发现,除了条件聚合,因为 Oracle 11 还有 PIVOT 运算符(但你标记了你的问题“Oracle10g”——如果那是你的版本,你不'还没有PIVOT)。 附注: 1. 不应再使用逗号分隔的连接。 Oracle 支持正确的 ANSI 连接很晚,但从版本 9i 开始支持。改用这些(例如from a join b on a.x = b.y)。 2. ORDER BY 不属于子查询。 3。 DISTINCT 通常表示查询写得不好。这两个函数调用真的是你想要加入表格的全部吗? @ThorstenKettner - 一般 ORDER BY 不属于子查询。有时确实如此。 【参考方案1】:

SELECT DISTINCT 几乎从不适合 GROUP BY

您的问题是您将(MONTHNAMESHORT) 包含在GROUP BY 中。

您的查询很难破译。但它应该看起来像这样:

SELECT SYEAR, DEPT_NAME,
       SUM(CASE WHEN upper(MONTHNAMESHORT) = 'JAN' THEN FirstLetter END) as "JAN1" ,  
       SUM(CASE WHEN upper(MONTHNAMESHORT) = 'JAN' THEN SecondLetter END) as "JAN2" ,  
       SUM(CASE WHEN upper(MONTHNAMESHORT) = 'FEB' THEN FirstLetter END) as "FEB1" ,  
       SUM(CASE WHEN upper(MONTHNAMESHORT) = 'FEB' THEN SecondLetter END) as "FEB2" 
FROM . . . 
GROUP BY SYEAR, DEPT_NAME;

【讨论】:

以上是关于分组依据创建重复行的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:分组重复行集

重复值的 Primefaces 行分组

实体框架 LINQ - 具有分组依据的子查询

mysql带条件查询,联表查询

mysql计算行并按月分组[重复]

如何对重复的行进行分组并计算它们?