运行 根据 Oracle 中的时间按项目重复分组的总数 SQL
Running total over repeating group by items based on time in Oracle SQL
我的第一个 post,所以请耐心等待。我想根据按日期分解的值求和,但只想要日期的总和,而不是总计按项目分组的总和。已经为此工作了好几天,试图避免使用游标,但可能不得不这样做。
这是我正在查看的数据示例。顺便说一句,这是在 Oracle 11g 中。
Key Time Amt
------ ------------------ ------
Null 1-1-2016 00:00 50
Null 1-1-2016 02:00 50
Key1 1-1-2016 04:00 30
Null 1-1-2016 06:00 30
Null 1-1-2016 08:00 30
Key2 1-1-2016 10:00 40
Null 1-1-2016 12:00 40
Key1 1-1-2016 14:00 30
Null 1-2-2016 00:00 30
Key2 1-2-2016 02:00 35
最终结果应该是这样的:
Key Start Stop Amt
------ ---------------- ---------------- -----
Null 1-1-2016 00:00 1-1-2016 02:00 100
Key1 1-1-2016 04:00 1-1-2016 08:00 90
Key2 1-1-2016 10:00 1-1-2016 12:00 80
Key1 1-1-2016 14:00 1-2-2016 00:00 60
key2 1-2-2016 02:00 1-2-2016 02:00 35
我已经获得了填空值的密钥。密钥并不总是输入,但在实际更改之前假定为值。
SELECT key ,time ,amt
FROM (
SELECT DISTINCT amt, time,
,last_value(amt ignore nulls) OVER (
ORDER BY time
) key
FROM sample
ORDER BY time, amt
)
WHERE amt > 0
ORDER BY time, key NULLS first;
但是当我试图只得到一个 运行 总数时,即使有中断,它也会在键上求和。我无法弄清楚如何让它打破关键。这是我最好的尝试,它不是很好而且不能正常工作。
SELECT key,time, amt
, sum(amt) OVER (PARTITION BY key ORDER BY time) AS running_total
FROM (SELECT key, time, amt
FROM (SELECT DISTINCT
amt,
time,
last_value(amt ignore nulls) OVER (ORDER BY time) key
FROM sample
ORDER BY time, amt
)
WHERE amt > 0
ORDER BY time, key NULLS first
)
ORDER BY time, key NULLS first;
如有任何帮助,我们将不胜感激。也许使用光标是唯一的方法。
匹配示例数据。
我不确定您的示例数据与查询有什么关系(例如,您的示例数据是一个 table,并且示例查询有很多查询)。但是,为了分配键,您可以使用 LAG()
和 IGNORE NULLS
选项:
select s.*,
lag(key ignore nulls) over (order by start) as new_key
from sample s;
然后,您想要将具有相同键的组组合在一起。一种方法是行号不同。最后一步是聚合:
select new_key, min(time), max(time), sum(amount)
from (select s.*,
(row_number() over (order by start) -
row_number() over (partition by new_key order by start)
) as grp
from (select s.*,
lag(key ignore nulls) over (order by start) as new_key
from sample s
) s
) s
group by new_key, grp;
为了获得您正在寻找的总和,您需要一种方法来对您感兴趣的值进行分组。您可以使用几个 ROW_NUMBER
分析函数生成一个分组 ID,其中一个是分区的通过键值。但是,由于您需要复制 KEY
列值,因此需要分几个阶段完成:
WITH t1 AS (
SELECT dta.*
, last_value(KEY IGNORE NULLS) -- Fill in the missing
OVER (ORDER BY TIME ASC) key2 -- key values
FROM your_data dta
), t2 AS (
SELECT t1.*
, row_number() OVER (ORDER BY TIME) -- Generate a
- row_number() OVER (PARTITION BY key2 -- grouping ID
ORDER BY TIME) gp
FROM t1
)
SELECT t2.*
, sum(amt) OVER (PARTITION BY gp, key2
ORDER BY TIME) running_sums
FROM t2;
上面的查询创建了一个 运行 的 AMT 总和,每次键值更改时都会重新启动。而用于代替上面最后一个 select 语句的以下查询给出了请求的结果,我不会将其称为 运行 总和。
SELECT key2
, MIN(TIME) start_time
, MAX(TIME) stop_time
, sum(amt) amt
FROM t2
GROUP BY key2, gp;
要查看完整时间值,您可能需要按以下方式更改会话 NLS_DATE_FORMAT
:
ALTER SESSION SET NLS_DATE_FORMAT='DD-MM-RRRR HH24:MI:SS';
或者将每个日期列包装在一个 TO_CHAR
函数中以用于输出目的。
每当 Key
不为 NULL 时分配一个组号可以很容易地与 LAG
:
一起计算
LAG(key ignore NULLS) OVER (ORDER BY time) AS new_key,
COUNT(key) OVER (ORDER BY time ROWS UNBOUNDED PRECEDING) AS grp
我的第一个 post,所以请耐心等待。我想根据按日期分解的值求和,但只想要日期的总和,而不是总计按项目分组的总和。已经为此工作了好几天,试图避免使用游标,但可能不得不这样做。
这是我正在查看的数据示例。顺便说一句,这是在 Oracle 11g 中。
Key Time Amt
------ ------------------ ------
Null 1-1-2016 00:00 50
Null 1-1-2016 02:00 50
Key1 1-1-2016 04:00 30
Null 1-1-2016 06:00 30
Null 1-1-2016 08:00 30
Key2 1-1-2016 10:00 40
Null 1-1-2016 12:00 40
Key1 1-1-2016 14:00 30
Null 1-2-2016 00:00 30
Key2 1-2-2016 02:00 35
最终结果应该是这样的:
Key Start Stop Amt
------ ---------------- ---------------- -----
Null 1-1-2016 00:00 1-1-2016 02:00 100
Key1 1-1-2016 04:00 1-1-2016 08:00 90
Key2 1-1-2016 10:00 1-1-2016 12:00 80
Key1 1-1-2016 14:00 1-2-2016 00:00 60
key2 1-2-2016 02:00 1-2-2016 02:00 35
我已经获得了填空值的密钥。密钥并不总是输入,但在实际更改之前假定为值。
SELECT key ,time ,amt
FROM (
SELECT DISTINCT amt, time,
,last_value(amt ignore nulls) OVER (
ORDER BY time
) key
FROM sample
ORDER BY time, amt
)
WHERE amt > 0
ORDER BY time, key NULLS first;
但是当我试图只得到一个 运行 总数时,即使有中断,它也会在键上求和。我无法弄清楚如何让它打破关键。这是我最好的尝试,它不是很好而且不能正常工作。
SELECT key,time, amt
, sum(amt) OVER (PARTITION BY key ORDER BY time) AS running_total
FROM (SELECT key, time, amt
FROM (SELECT DISTINCT
amt,
time,
last_value(amt ignore nulls) OVER (ORDER BY time) key
FROM sample
ORDER BY time, amt
)
WHERE amt > 0
ORDER BY time, key NULLS first
)
ORDER BY time, key NULLS first;
如有任何帮助,我们将不胜感激。也许使用光标是唯一的方法。
匹配示例数据。
我不确定您的示例数据与查询有什么关系(例如,您的示例数据是一个 table,并且示例查询有很多查询)。但是,为了分配键,您可以使用 LAG()
和 IGNORE NULLS
选项:
select s.*,
lag(key ignore nulls) over (order by start) as new_key
from sample s;
然后,您想要将具有相同键的组组合在一起。一种方法是行号不同。最后一步是聚合:
select new_key, min(time), max(time), sum(amount)
from (select s.*,
(row_number() over (order by start) -
row_number() over (partition by new_key order by start)
) as grp
from (select s.*,
lag(key ignore nulls) over (order by start) as new_key
from sample s
) s
) s
group by new_key, grp;
为了获得您正在寻找的总和,您需要一种方法来对您感兴趣的值进行分组。您可以使用几个 ROW_NUMBER
分析函数生成一个分组 ID,其中一个是分区的通过键值。但是,由于您需要复制 KEY
列值,因此需要分几个阶段完成:
WITH t1 AS (
SELECT dta.*
, last_value(KEY IGNORE NULLS) -- Fill in the missing
OVER (ORDER BY TIME ASC) key2 -- key values
FROM your_data dta
), t2 AS (
SELECT t1.*
, row_number() OVER (ORDER BY TIME) -- Generate a
- row_number() OVER (PARTITION BY key2 -- grouping ID
ORDER BY TIME) gp
FROM t1
)
SELECT t2.*
, sum(amt) OVER (PARTITION BY gp, key2
ORDER BY TIME) running_sums
FROM t2;
上面的查询创建了一个 运行 的 AMT 总和,每次键值更改时都会重新启动。而用于代替上面最后一个 select 语句的以下查询给出了请求的结果,我不会将其称为 运行 总和。
SELECT key2
, MIN(TIME) start_time
, MAX(TIME) stop_time
, sum(amt) amt
FROM t2
GROUP BY key2, gp;
要查看完整时间值,您可能需要按以下方式更改会话 NLS_DATE_FORMAT
:
ALTER SESSION SET NLS_DATE_FORMAT='DD-MM-RRRR HH24:MI:SS';
或者将每个日期列包装在一个 TO_CHAR
函数中以用于输出目的。
每当 Key
不为 NULL 时分配一个组号可以很容易地与 LAG
:
LAG(key ignore NULLS) OVER (ORDER BY time) AS new_key,
COUNT(key) OVER (ORDER BY time ROWS UNBOUNDED PRECEDING) AS grp