SQL - 计算分区
Posted
技术标签:
【中文标题】SQL - 计算分区【英文标题】:SQL - count over partition 【发布时间】:2016-11-16 15:11:41 【问题描述】:请告诉我这有什么问题:
select
p.date,
(SELECT COUNT (*) OVER (PARTITION BY p.ID_code)
FROM POOL_AREA.F_volume_GCOA p
WHERE p.end_volume_KN <> 0
AND p.date = '31-OCT-16'
AND (p.local_grade_MB IS NULL OR p.local_grade_MB ='0' OR p.local_grade_MB ='N')) AS ERROR_CNT
FROM POOL_AREA.F_volume_GCOA p
where p.date = '31-OCT-16';
过度分区部分是问题,没有它,它可以工作。
错误详情: ORA-01427: 单行子查询返回多于一行 01427. 00000 - “单行子查询返回多行” *原因: *行动:
【问题讨论】:
首先,您有一个Oracle
错误消息,但您将问题标记为mysql
和SQL Server
。
通过分区你会得到不止一个结果。在您的选择中,它可能只有一个值。您可以加入子查询而不是将其添加到您的 SELECT
为什么这里有一个子查询? date
也是保留字,不是有效的列名; '31-OCT-16' 是字符串而不是日期。如果您使用正确的数据类型,生活会更轻松。有一列存储“N”和“0”看起来也很奇怪。
@Ema 顺便说一句,p.date
是什么数据类型?如果是 DATE,那么您不应该将日期与字符串进行比较。 IE。将p.date = '31-OCT-16'
更改为p.date = to_date('31/10/2016', 'dd/mm/yyyy')
。这样,您就不会依赖 nls_date_format 参数来管理隐式转换。特别是如果这种情况发生了变化,您的代码很可能会失败。
按您未显示的列进行分区也有点奇怪。您确定要分析计数,而不是汇总吗?您能否编辑问题以包含表结构、一些示例数据和您要查找的结果?
【参考方案1】:
我认为你真正追求的是条件计数 - 类似于:
select p.dt,
count(case when p.end_volume_kn != 0
and (p.local_grade_mb is null
or p.local_grade_mb in ('0', 'N'))
then 1
end) error_cnt
FROM POOL_AREA.F_volume_GCOA p
where p.dt = to_date('31/10/2016', 'dd/mm/yyyy')
group by p.dt;
【讨论】:
【参考方案2】:如 cmets 中所述,类似这样的内容(未测试):
select
p.date,
t.val AS ERROR_CNT
FROM POOL_AREA.F_volume_GCOA p
JOIN (SELECT p.ID_code, COUNT (*) as val OVER (PARTITION BY p2.ID_code)
FROM POOL_AREA.F_volume_GCOA p2
WHERE p2.end_volume_KN <> 0
AND p2.date = '31-OCT-16'
AND (p2.local_grade_MB IS NULL OR p2.local_grade_MB ='0'
OR p.local_grade_MB ='N')) as t ON t.ID_Code = p.ID_code
where p.date = '31-OCT-16';
【讨论】:
【参考方案3】:这行得通!
select
p.date,
(SELECT COUNT (*) FROM
(SELECT DISTINCT p.id_code
FROM POOL_AREA.F_volume_GCOA p
WHERE p.end_volume_KN <> 0
AND p.date = '31-OCT-16'
AND (p.local_grade_MB IS NULL OR p.local_grade_MB ='0' OR p.local_grade_MB ='N'))) AS ERROR_CNT
FROM POOL_AREA.F_volume_GCOA p
where p.date = '31-OCT-16';
【讨论】:
以上是关于SQL - 计算分区的主要内容,如果未能解决你的问题,请参考以下文章