'Total count before each month
I would like to calculate the total count before each individual month. Imagine that i have a table like this:
table "order": order_id(int), order_state(varchar2), changed_on(date)
order_state column has only 3 states - open, on_going and closed.
I would like to know before and for each month of the current fiscal year, how many where in on_going until each month.
example:
| order_id | order_state | changed_on |
|---|---|---|
| 3 | OPEN | 1-12-21 |
| 2 | OPEN | 1-12-21 |
| 1 | ON_GOING | 2-12-21 |
| 3 | ON_GOING | 4-12-21 |
| 23 | ON_GOING | 1-1-22 |
| 1 | CLOSED | 2-1-22 |
The results should be
| count(*) | date |
|---|---|
| 0 | OCT-21 |
| 0 | NOV-21 |
| 2 | DEC-21 |
| 2 | JAN-22 |
| 2 | FEB-22 |
| 2 | MAR-22 |
| 2 | APR-22 |
| 2 | MAI-22 |
| 0 | JUN-22 |
| 0 | JUL-22 |
| 0 | AUG-22 |
| 0 | SET-22 |
For 12-21 it should include order 1 and 3
For 1-22, order id 1 has been closed, include order 3 and 23
Assuming that current sysdate is May 22, until the end of the fiscal year it should return zero for future months.
This is where i'm at with the query
with fiscal_year_months as (
select to_char(add_months(to_date('01-10' || (to_number(to_char(sysdate, 'RRRR'))-1), 'DD-MM-RRRR', rownum -1), 'Month RRRR') mth from dual connect by rownum <=12
)
select count(*), changed_on
from orders
where order_state = 'ON_GOING'
right outer join fisca_year_months fym on fym.mth = orders.changed_on
order_by to_date(orders.changed_on, 'MM-RRRR')
but this query gives me the count for each individual month. And i want the count until the calculated month.
Solution 1:[1]
You can use a PARTITIONed OUTER JOIN and the LAST_VALUE analytic function to find the most recent statuses for each order and then can aggregate:
WITH calendar(month) AS (
SELECT ADD_MONTHS(DATE '2021-10-01', LEVEL -1)
FROM DUAL
CONNECT BY LEVEL <= 12
)
SELECT month,
SUM(status) AS cnt
FROM (
SELECT month,
order_id,
MAX(
CASE
WHEN month <= SYSDATE AND status IN ('ON_GOING') THEN 1
ELSE 0
END
) AS status
FROM (
SELECT c.month,
t.order_id,
LAST_VALUE(t.order_state) IGNORE NULLS
OVER (PARTITION BY t.order_id ORDER BY c.month, t.changed_on)
AS status
FROM calendar c
LEFT OUTER JOIN table_name t
PARTITION BY (t.order_id)
ON (c.month = TRUNC(t.changed_on, 'MM'))
)
GROUP BY
month,
order_id
)
GROUP BY month;
Which, for your sample data:
CREATE TABLE table_name (order_id, order_state, changed_on) AS
SELECT 3, 'OPEN', DATE '2021-12-01' FROM DUAL UNION ALL
SELECT 2, 'OPEN', DATE '2021-12-01' FROM DUAL UNION ALL
SELECT 1, 'ON_GOING', DATE '2021-12-02' FROM DUAL UNION ALL
SELECT 3, 'ON_GOING', DATE '2021-12-04' FROM DUAL UNION ALL
SELECT 23, 'ON_GOING', DATE '2022-01-01' FROM DUAL UNION ALL
SELECT 1, 'CLOSED', DATE '2022-01-02' FROM DUAL;
Outputs:
MONTH CNT 2021-10-01 00:00:00 0 2021-11-01 00:00:00 0 2021-12-01 00:00:00 2 2022-01-01 00:00:00 2 2022-02-01 00:00:00 2 2022-03-01 00:00:00 2 2022-04-01 00:00:00 2 2022-05-01 00:00:00 2 2022-06-01 00:00:00 0 2022-07-01 00:00:00 0 2022-08-01 00:00:00 0 2022-09-01 00:00:00 0
db<>fiddle here
Solution 2:[2]
Here's revised version of your code:
magnet.go:
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"strconv"
)
func nGroups(r io.Reader, w io.Writer) (int, error) {
if _, ok := r.(*bufio.Reader); !ok {
r = bufio.NewReader(r)
}
br := r.(*bufio.Reader)
buf, err := br.ReadBytes('\n')
if err != nil {
return 0, err
}
n, err := strconv.Atoi(string(bytes.TrimSpace(buf)))
if err != nil {
return 0, err
}
ng := 0
var prev byte
for i := 0; i < n; i++ {
m, err := br.ReadSlice('\n')
if err != nil {
if err != io.EOF || i < n-1 {
return 0, err
}
}
if m[0] != prev {
ng++
}
prev = m[0]
}
return ng, nil
}
func main() {
ng, err := nGroups(os.Stdin, os.Stdout)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(ng)
}
A Go benchmark of 100,000 magnets seems to indicate that it's faster than your version.
rocka2q:
Benchmark100KR-8 1012 1177446 ns/op 4336 B/op 7 allocs/op
moogod:
Benchmark100KM-8 5 245167574 ns/op 5001715 B/op 200011 allocs/op
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
