我正在使用Postgres(PL/pgSQL)开发一个算法,我需要计算两个时间戳之间的工作小时数,考虑到周末不工作,剩下的时间只计算在上午8点到下午15点.
例子:
从12月3日下午14点到12月4日上午9点应该计算2个小时:
3rd = 1, 4th = 1
Run Code Online (Sandbox Code Playgroud)从12月3日下午15点到12月7日上午8点,应该计算8小时:
3rd = 0, 4th = 8, 5th = 0, 6th = 0, 7th = 0
Run Code Online (Sandbox Code Playgroud)考虑小时分数也会很棒.
我有一个表格,用于跟踪某些商店和产品的库存随时间的变化。该值是绝对库存,但我们仅在库存发生变化时插入新行。这种设计是为了保持表较小,因为预计它会快速增长。
这是一个示例架构和一些测试数据:
CREATE TABLE stocks (
id serial NOT NULL,
store_id integer NOT NULL,
product_id integer NOT NULL,
date date NOT NULL,
value integer NOT NULL,
CONSTRAINT stocks_pkey PRIMARY KEY (id),
CONSTRAINT stocks_store_id_product_id_date_key
UNIQUE (store_id, product_id, date)
);
insert into stocks(store_id, product_id, date, value) values
(1,10,'2013-01-05', 4),
(1,10,'2013-01-09', 7),
(1,10,'2013-01-11', 5),
(1,11,'2013-01-05', 8),
(2,10,'2013-01-04', 12),
(2,11,'2012-12-04', 23);
Run Code Online (Sandbox Code Playgroud)
我需要能够确定每个产品和商店的开始日期和结束日期之间的平均库存,但我的问题是简单的 avg() 没有考虑到库存在更改之间保持不变。
我想要的是这样的:
select s.store_id, s.product_id , special_avg(s.value)
from stocks s where s.date between '2013-01-01' and '2013-01-15'
group by s.store_id, s.product_id
Run Code Online (Sandbox Code Playgroud)
结果是这样的: …
当查询中有许多其他列时,是否有适当的方法聚合单个列?
我已经试过了这个有效的答案,但是我的查询变得更加冗长。
我当前的查询如下所示:
SELECT t1.foo1, t1.foo2, t2.foo3, t2.foo4, string_agg(t3.aggregated_field, ', ')
FROM tbl1 t1
LEFT JOIN tbl2 t2 ON t1.id = t2.fkeyid
LEFT JOIN tbl3 t3 ON t2.id = t3.fkeyid
GROUP BY t1.foo1, t1.foo2, t2.foo3, t2.foo4, t2.foo5, t2.foo6
ORDER BY t2.foo5, t2.foo6
Run Code Online (Sandbox Code Playgroud)
该查询具有更多字段和LEFT JOINs,重要的部分是所有这些字段都具有1到1或1到0的关系,除了上面要t3.aggregated_field在上面的伪查询中表示的要聚合的1到n的一个字段。
当我使用汇总函数时,SELECT和中列出的所有字段都ORDER BY必须汇总或成为GROUP BY子句的一部分。这使我的查询方式比现在更加冗长。
也就是说,假设foo1是主键,则在重复此字段时,除其他字段外的所有其他字段aggregated_field也相等。我希望将这些重复的行作为具有聚合字段值的单行结果。(基本上是a select distinct,带有汇总列)
是否有更好的方法来执行此操作(而不必将所有其他字段都放入GROUP BY),还是应该仅对后端执行的结果集进行迭代,以对获取此1到n关系的每一行执行查询?
服务器正在运行PostgreSQL 9.1.9,更具体地说:
x86_64-unknown-linux-gnu上的PostgreSQL 9.1.9,由gcc(GCC)4.1.2 20080704(Red Hat 4.1.2-54)编译,64位