Domanda

I have made a query to bring me the number of products that have not been in stock (I know that by looking at the orders which the manufacturer returned with some status code), by product, date and storage, that looks like this:

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

That produces an answer like this:

 out_of_stock | product_id | date        | storage_id
--------------|------------|-------------|-------------
 1            | 5          | 2012-10-16  | 1
 5            | 4          | 2012-10-16  | 2

Now I need to get the number of occurrences, by product and storage, of products that have been out of stock for 2 or more days, 5 or more days and so on.
So I guess I need to do a new count on the first query, aggregating the resultant rows in some defined day intervals.

I tried looking at the datetime functions in Postgres (http://www.postgresql.org/docs/7.3/static/functions-datetime.html), but couldn't find what I need.

È stato utile?

Soluzione 2

Since you seem to want every row in the result individually, you cannot aggregate. Use a window function instead to get the count per day. The well known aggregate function count() can also serve as window aggregate function:

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

Sort order: Products having been out of stock for the longest time first.
Note, you can just subtract dates to get an integer in Postgres.

If you want a running count in the sense of "n rows have been out of stock for this number of days or more", use:

count(*) OVER (ORDER BY ped.data_envio::date) -- ascending order!
                                        AS running_count_per_days_out_of_stock

You get the same count for the same day, peers are lumped together.

Altri suggerimenti

May be I didn't get correctly you question, but it looks you need leverage sub-query.

Now I need to get the number of occurrences, by product and storage, of products that have been out of stock for 2 or more days

So:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top