在 oracle 的 sql 查询中替换 "filter"
substituting "filter" in a sql query on oracle
我们有一个 table 数据,其中一个日期列指示数据的日期 ("planning_day") 和另一列用于记录数据发送时间 ("first_sent_time").
我正在尝试制作一份报告,显示我们在哪一天发送了 past/future 数据。所以如果今天我们发送 2 个昨天的数据,5 个今天的数据和 1 个后天的数据,结果应该是这样的:
sent_day minus2 minus1 sameDay plus1 plus2
2021-11-24 0 2 5 0 1
...
我知道我可以在 postgres 中通过使用“过滤器”的查询来做到这一点:
select
trunc(t.first_sent_time),
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = -2) as "minus2",
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = -1) as "minus1",
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = 0) as "sameDay",
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = 1) as "plus1",
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = 2) as "plus2"
from
my_table t
group by
trunc(t.first_sent_time)
;
不幸的是,这个“过滤器”在 Oracle 中不存在。我在这里需要帮助。我尝试了如下操作:
select
sent_day,
sum(minus2),
sum(minus1),
sum(sameDay),
sum(plus1),
sum(plus2)
from (
select
*
from (
select
b.id,
trunc(b.first_sent_time) as sent_day,
b.planning_day,
b.planning_day - trunc(b.first_sent_time) as day_diff
from
my_table b
where
b.first_sent_time >= DATE '2021-11-01'
)
pivot (
count(id) for day_diff in (-2 as "minus2",-1 as "minus1",0 as "sameDay", 1 as "plus1",2 as "plus2")
)
)
group by
sent_day
order by
sent_day
;
但它不起作用,感觉我走得太复杂了,必须有一个更简单的解决方案。
在聚合函数中使用CASE
表达式来模拟filter
。
这里是一个简化的例子
with dt as (
select 1 id , 1 diff_days from dual union all
select 2 id , 1 diff_days from dual union all
select 3 id , -1 diff_days from dual union all
select 4 id , -1 diff_days from dual union all
select 4 id , -1 diff_days from dual)
/* query */
select
count(case when diff_days = 1 then id end) as cnt_1,
count(case when diff_days = -1 then id end) as cnt_minus_1
from dt;
结果
CNT_1 CNT_MINUS_1
---------- -----------
2 3
我们有一个 table 数据,其中一个日期列指示数据的日期 ("planning_day") 和另一列用于记录数据发送时间 ("first_sent_time").
我正在尝试制作一份报告,显示我们在哪一天发送了 past/future 数据。所以如果今天我们发送 2 个昨天的数据,5 个今天的数据和 1 个后天的数据,结果应该是这样的:
sent_day minus2 minus1 sameDay plus1 plus2
2021-11-24 0 2 5 0 1
...
我知道我可以在 postgres 中通过使用“过滤器”的查询来做到这一点:
select
trunc(t.first_sent_time),
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = -2) as "minus2",
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = -1) as "minus1",
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = 0) as "sameDay",
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = 1) as "plus1",
count(t.id) filter (where e.planning_day - trunc(e.first_sent_time) = 2) as "plus2"
from
my_table t
group by
trunc(t.first_sent_time)
;
不幸的是,这个“过滤器”在 Oracle 中不存在。我在这里需要帮助。我尝试了如下操作:
select
sent_day,
sum(minus2),
sum(minus1),
sum(sameDay),
sum(plus1),
sum(plus2)
from (
select
*
from (
select
b.id,
trunc(b.first_sent_time) as sent_day,
b.planning_day,
b.planning_day - trunc(b.first_sent_time) as day_diff
from
my_table b
where
b.first_sent_time >= DATE '2021-11-01'
)
pivot (
count(id) for day_diff in (-2 as "minus2",-1 as "minus1",0 as "sameDay", 1 as "plus1",2 as "plus2")
)
)
group by
sent_day
order by
sent_day
;
但它不起作用,感觉我走得太复杂了,必须有一个更简单的解决方案。
在聚合函数中使用CASE
表达式来模拟filter
。
这里是一个简化的例子
with dt as (
select 1 id , 1 diff_days from dual union all
select 2 id , 1 diff_days from dual union all
select 3 id , -1 diff_days from dual union all
select 4 id , -1 diff_days from dual union all
select 4 id , -1 diff_days from dual)
/* query */
select
count(case when diff_days = 1 then id end) as cnt_1,
count(case when diff_days = -1 then id end) as cnt_minus_1
from dt;
结果
CNT_1 CNT_MINUS_1
---------- -----------
2 3