计算按某些行分组的出现次数
Posted
技术标签:
【中文标题】计算按某些行分组的出现次数【英文标题】:Count the number of occurrences grouped by some rows 【发布时间】:2013-09-27 14:25:16 【问题描述】:我查询了未库存的产品数量(通过查看制造商返回的带有一些状态代码的订单我知道),按产品、日期和存储,看起来像这个:
SELECT count(*) as out_of_stock,
prod.id as product_id,
ped.data_envio::date as date,
opl.id as storage_id
from sub_produtos_pedidos spp
left join cad_produtos prod ON spp.ean_produto = prod.cod_ean
left join sub_pedidos sp ON spp.id_pedido = sp.id
left join pedidos ped ON sp.id_pedido = ped.id
left join op_logisticos opl ON sp.id_op_logistico = opl.id
where spp.motivo = '201' -- this is the code that means 'not in inventory'
group by storage_id,product_id,date
这会产生这样的答案:
out_of_stock | product_id | date | storage_id
--------------|------------|-------------|-------------
1 | 5 | 2012-10-16 | 1
5 | 4 | 2012-10-16 | 2
现在我需要获取缺货 2 天或更长时间、5 天或更长时间等产品的出现次数(按产品和存储)。 所以我想我需要对第一个查询做一个新的计数,在一些定义的天间隔内聚合结果行。
我尝试查看 Postgres (http://www.postgresql.org/docs/7.3/static/functions-datetime.html) 中的日期时间函数,但找不到我需要的。
【问题讨论】:
您需要告诉我们更多关于表之间的关系。这些是1:1的关系吗?还是 1:n?为什么要使用 LEFT JOIN?哪些表不能有匹配的行? 【参考方案1】:可能是我没有正确回答您的问题,但看起来您需要利用子查询。
现在我需要按产品和存储获取缺货 2 天或更长时间的产品的出现次数
所以:
SELECT COUNT(*), date, product_id FROM ( YOUR BIG QUERY IS THERE ) a
WHERE a.date < (CURRENT_DATE - interval '2' day)
GROUP BY date, product_id
【讨论】:
我尝试过类似的方法。但我真正需要的是把答案分成不同的组:“缺货两天或更长时间的产品”、“缺货五天或更长时间的产品”、“已经缺货的产品”库存十天或更长时间”,按存储设施。我不知道在 SQL 中是否有一种简单的方法可以做到这一点。我需要把它放到一个OLAP多维数据集中生成报告,也许用MDX查询多维数据集更容易......【参考方案2】:由于您似乎希望结果中的每一行都单独,因此您无法汇总。改为使用window function 来获取每天的计数。众所周知的聚合函数count()
也可以作为窗口聚合函数:
SELECT current_date - ped.data_envio::date AS days_out_of_stock
,count(*) OVER (PARTITION BY ped.data_envio::date)
AS count_per_days_out_of_stock
,ped.data_envio::date AS date
,p.id AS product_id
,opl.id AS storage_id
FROM sub_produtos_pedidos spp
LEFT JOIN cad_produtos p ON p.cod_ean = spp.ean_produto
LEFT JOIN sub_pedidos sp ON sp.id = spp.id_pedido
LEFT JOIN op_logisticos opl ON opl.id = sp.id_op_logistico
LEFT JOIN pedidos ped ON ped.id = sp.id_pedido
WHERE spp.motivo = '201' -- code for 'not in inventory'
ORDER BY ped.data_envio::date, p.id, opl.id
排序顺序:首先是缺货时间最长的产品。
请注意,您可以在 Postgres 中减去 dates
以得到 integer
。
如果您想要运行计数,即“n 行已缺货此天数或更多”,请使用:
count(*) OVER (ORDER BY ped.data_envio::date) -- ascending order!
AS running_count_per_days_out_of_stock
您在同一天获得相同的计数,同行被归为一类。
【讨论】:
以上是关于计算按某些行分组的出现次数的主要内容,如果未能解决你的问题,请参考以下文章