分组依据创建重复行
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;
【讨论】:
以上是关于分组依据创建重复行的主要内容,如果未能解决你的问题,请参考以下文章