【发布时间】:2018-03-11 19:18:49
【问题描述】:
我有一张这样的桌子:
|Date |Type |MetricA|MetricB|
|01-01|House|0 |500 |
|01-01|Paid |1 |1000 |
|01-01|Paid |1 |4000 |
|02-01|House|0 |3000 |
|02-01|Paid |10 |13000 |
|02-01|House|0 |5000 |
|02-01|Paid |5 |10000 |
|02-01|Paid |1 |1500 |
我想计算第三个指标 (1000*MetricA / MetricB),我还希望 MetricB 按类型拆分,这样我的最终表格如下所示:
|Date |Metric_House|Metric_Paid|MetricA|NewMetric
|01-01|500 |5000 |2 |0.40
|02-01|8000 |24500 |16 |0.653061224
(我希望表结构有意义,否则我可以在这里给你截图:https://i.imgur.com/5HZiMh8.png)
我想出了如何正确编写 Metric_House、Metric_Paid、MetricA 列,但我正在努力编写 NewMetric。
有时 MetricB == 0,然后我可以除以 0。我可以编写一个 case 函数,但是我遇到了聚合求和的麻烦。我花了几个小时尝试为此编写查询,但我无法弄清楚:( 我试过这个:
func.sum(case([((i.c.metricb) != 0, 1000*func.sum(i.c.metrica)/i.c.metricb)], else_=0))
这是 SQLAlchemy(SQL 之上的 Python 层),但它基本上是:
SUM(CASE WHEN METRIC != 0 THEN 1000*SUM(METRICA)/SUM(METRICB) ELSE 0
在该查询之后我得到一个嵌套错误。
我在 Python 框架中工作,当我忽略查询中的 NewMetric 列并随后使用简单的列表函数添加它时,我在几分钟内就完成了。但我宁愿在 SQL 内部而不是外部处理数据。 编写此查询的最佳方式是什么?提前致谢!
编辑:
这是我的工作:
stmt = select([i.c.date,
cast(func.sum(case([(
i.c.type != 'House', i.c.metricb)], else_=0)),
Integer).label('metric_paid'),
cast(func.sum(case([(
i.c.type == 'House', i.c.metricb)], else_=0)),
Integer).label('metric_house'),
cast(func.sum(i.c.metrica), Float).label('metrica')]).group_by(
i.c.date).order_by(asc(i.c.date))
现在这是我尝试过的(添加这个额外的表达式):
case([(sum(i.c.metricb) != 0,
1000*sum(i.c.metrica)/sum(i.c.metricb))], else_=0)])
NotImplementedError:此表达式不支持运算符“getitem”
func.sum(case([(i.c.metricb!= 0,
1000*func.sum(i.c.metrica)/func.sum(i.c.metricb))], else_=0))
(psycopg2.ProgrammingError) 聚合函数调用不能嵌套 LINE 1: ...i.metricb != 0) THEN (1000 * sum(i...
更多的尝试和错误:
case([(and_(func.sum(i.c.metricb) != 0, (i.c.type) != 'House'), 1000*func.sum(i.c.metrica)/func.sum(i.c.metricb))])
ProgrammingError: (psycopg2.ProgrammingError) 列“type”必须出现在 GROUP BY 子句中或用于聚合函数中
但是我不想要group by子句中的type列,那不会产生错误的结果
【问题讨论】:
-
做一个 GROUP BY。在选择列表中使用案例表达式来选择每个“类型”。还有另一种避免被零除的情况。
-
“我在那个查询之后得到一个嵌套错误。”这意味着什么?解释器肯定会引发异常并向您显示堆栈跟踪,您应该在问题中提供此信息。
-
感谢 jarlh 的回答。我使用 group by 作为日期。我还需要分组什么? Giacomo,我得到的错误是 ProgrammingError: (psycopg2.ProgrammingError) 聚合函数调用不能嵌套 LINE 1: ...i.metricb != 0) THEN (1000 * sum(i...
-
您实际上拥有
SUM(SUM()),因此您会收到错误消息。与 CASE 无关。请生成minimal reproducible example,或者换句话说,包括相关模型/表的相关部分以及您正在使用的实际查询语句。 Python 构造与您提供的 SQL 不匹配。还包括问题中的回溯。您已标记此 mysql,但回溯 sn-p 提示 Postgresql... -
糟糕,你是对的,我在 postgresql 中工作,而不是 mysql;我已经在标记中更改了这一点,抱歉。我还编辑了原始问题并提供了我正在使用的陈述。感谢您的帮助!
标签: python sql postgresql sqlalchemy