Mysql Postgresql 9.4:在同一查询中使用计算列,并按月对部分结果进行分组
我正在查询postgresql 9.4数据库,希望使用同一查询中的列执行计算 我试图获得的结果是一个基于总天数的部分值。例如Mysql Postgresql 9.4:在同一查询中使用计算列,并按月对部分结果进行分组,mysql,postgresql,postgresql-9.4,integral,Mysql,Postgresql,Postgresql 9.4,Integral,我正在查询postgresql 9.4数据库,希望使用同一查询中的列执行计算 我试图获得的结果是一个基于总天数的部分值。例如 开工日期:2016年1月1日 持续时间(以月为单位):2 总天数:60天 价值x:120 如果我今天(2016年1月5日)启动查询,我希望获得: partial_result = value_x * passed_days / total_days 120 * 5 / 60 在我的数据集中,我有超过1
- 开工日期:2016年1月1日
- 持续时间(以月为单位):2
- 总天数:60天
- 价值x:120
partial_result = value_x * passed_days / total_days
120 * 5 / 60
在我的数据集中,我有超过10万条记录,我需要按月将这个部分值分组(按月添加部分值)
=========================================================================
WITH time_ranges AS (
SELECT to_date('2014-07-01', 'yyyy-mm-dd') as START_DATE, to_date('2014-07-31', 'yyyy-mm-dd') as END_DATE
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-08-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-09-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-10-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-11-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-12-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-01-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-02-28', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-03-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-04-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-05-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-06-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-07-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-08-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-09-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-10-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-11-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-12-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2016-01-05', 'yyyy-mm-dd')
)
SELECT time_ranges.end_date, round(SUM(gross_pdu * LEAST(total_days, GREATEST( EXTRACT(DAY FROM(time_ranges.end_date - guarantees_days.start_date)), 0) ) / total_days)::numeric, 2)
FROM
(SELECT
*,
EXTRACT(DAY FROM (start_date + (duration_in_months || ' month')::INTERVAL) - start_date) as total_days
FROM subscribed_guarantees
) as guarantees_days
INNER JOIN
time_ranges ON
time_ranges.start_date <= guarantees_days.start_date AND guarantees_days.start_date <= time_ranges.end_date
WHERE INSURANCE_COMPANY = 'INSURANCE COMPANY' AND TAX = 13.5
GROUP BY
time_ranges.end_date
ORDER BY
time_ranges.end_date
在MySQL中,我可以进行如下计算:
SELECT
start_date,
duration_in_months,
@end_date:= DATE_ADD(start_date, INTERVAL duration_in_months MONTH) as end_date,
@total_days:= DATEDIFF(@end_date, start_date),
@passed_days:= DATEDIFF(CURDATE(), start_date),
value_x,
(value_x * @passed_days / @total_days) as partial_result
FROM table;
按照本文中的说明,我目前正在PostgreSQL中使用如下查询:
SELECT
start_date,
duration_in_months,
end_date,
total_days,
value_x,
(value_x * passed_days / total_days) as partial_result
FROM (SELECT *,
(start_date + (duration_in_months || ' month')::INTERVAL) as end_date,
EXTRACT(DAY FROM (start_date + (duration_in_months || ' month')::INTERVAL) - start_date) as total_days,
EXTRACT(DAY FROM current_date - start_date) as passed_days
FROM table) as table1;
我需要您的帮助,以便:
- 在PostgreSQL中使用计算变量,就像在MySQL中一样在查询中使用公式,或者找到其他方法使查询更具可读性
- 将分部结果按月份分组
- 插入where子句以确保
passed_days>=0且passed_days首先,您的MySQL查询不能保证工作。MySQL文档非常明确,
中表达式的求值顺序可以是任意的。因此,可以在设置变量之前计算最后一个表达式(实际上,它们将被设置为前一行中的值) 在Postgres中,我认为您对子查询或CTE的想法是正确的。您只需引用不带SELECT
的列。我不知道具体的日期算法是否正确,但这是等效的查询:@
SELECT start_date, duration_in_months, end_date, total_days, value_x, (value_x * passed_days / total_days) as partial_result FROM (SELECT t.*, (start_date + (duration_in_months || ' month')::INTERVAL) as end_date, EXTRACT(DAY FROM (start_date + (duration_in_months || ' month')::INTERVAL) - start_date) as total_days, EXTRACT(DAY FROM current_date - start_date) as passed_days FROM table t ) t;
在我看来是错误的,但您是从extract(day)
间隔中提取日期,而不是从日期/时间表达式中提取。我认为它可以满足您的需要。因为您的表达式相互使用,所以应该使用多个子查询(如果您不想重复任何表达式) 或者,您可以使用f.ex:
可以在PostgreSQL中使用DATEDIFF
进行计算,无需使用date1-date2
(但参数的类型必须为EXTRACT
;date
差异产生timestamp(tz)
s)interval
您可以使用来约束
(如果您想选择所有行),但如果您愿意,也可以在通过的天数
中的
中使用
。我在PostgreSQL中找到了一个合适的解决方案:通过的天数
- 按月分组:在查询开始时与table as()语句一起使用。然后做一个内部连接
- 声明变量:使用子查询
时间范围如下的WITH time_ranges AS ( SELECT to_date('2014-07-01', 'yyyy-mm-dd') as START_DATE, to_date('2014-07-31', 'yyyy-mm-dd') as END_DATE UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-08-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-09-30', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-10-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-11-30', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-12-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-01-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-02-28', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-03-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-04-30', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-05-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-06-30', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-07-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-08-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-09-30', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-10-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-11-30', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-12-31', 'yyyy-mm-dd') UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2016-01-05', 'yyyy-mm-dd') ) SELECT time_ranges.end_date, round(SUM(gross_pdu * LEAST(total_days, GREATEST( EXTRACT(DAY FROM(time_ranges.end_date - guarantees_days.start_date)), 0) ) / total_days)::numeric, 2) FROM (SELECT *, EXTRACT(DAY FROM (start_date + (duration_in_months || ' month')::INTERVAL) - start_date) as total_days FROM subscribed_guarantees ) as guarantees_days INNER JOIN time_ranges ON time_ranges.start_date <= guarantees_days.start_date AND guarantees_days.start_date <= time_ranges.end_date WHERE INSURANCE_COMPANY = 'INSURANCE COMPANY' AND TAX = 13.5 GROUP BY time_ranges.end_date ORDER BY time_ranges.end_date
( 选择截止日期(“2014-07-01”、“yyyy-mm-dd”)作为开始日期,选择截止日期(“2014-07-31”、“yyyy-mm-dd”)作为结束日期 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2014-08-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2014-09-30”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2014-10-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2014-11-30”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2014-12-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-01-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-02-28”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-03-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-04-30”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-05-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-06-30”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-07-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-08-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-09-30”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-10-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-11-30”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2015-12-31”、“yyyy-mm-dd”) 工会选择截止日期(“2014-07-01”、“yyyy-mm-dd”)和截止日期(“2016-01-05”、“yyyy-mm-dd”) ) 选择时间范围。结束日期,四舍五入(总和(总pdu*最小(总天数),最大(提取(日期从(时间范围。结束日期-保证天数。开始日期)),0))/总天数)::数字,2) 从…起 (选择 *, 提取(从(开始日期+(持续时间以月为单位)::间隔)-开始日期)起的天作为总天数 从认购的担保中 )就像你的日子一样 内连接 时间范围
谢谢你的回答。所以你认为在博士后中没有更好的方法吗?你将如何按月份对部分结果进行分组?以及如何确保通过天数为最大(通过天数,0)和最小(通过天数,总天数)?@mabe02。我在MySQL代码中没有看到任何这样的检查。但是在这两个数据库中,您都可以使用
和least()
。您能提供一些详细信息吗,比如您查询的表的DDL?你也可以用它;)创建表订阅担保(id整数、保险公司字符变化、总pdu数字(8,2)、税数字(8,2)、无时区的开始日期时间戳、持续时间(以月为单位)整数、“数字”整数、车牌字符变化、客户姓氏字符变化、客户姓名字符变化、经销商名称字符变化、产品描述字符变化、汽车信息模型grest()