我有一个包含(简单),用户,操作,日期的日志表。 有两种操作:搜索和查看(搜索可能返回一百条记录;用户可以查看零个或更多)。
我需要按日期对基本输出进行排序,但是我也需要将所有视图一起用于一次搜索。像
name operation date
john search 1/1 1pm
john view 1/1 2pm
john view 1/1 3pm
james search 1/1 230pm
james view 1/1 315pm
john search 1/1 310pm
似乎我需要使用子查询的结果来执行查询,但是我不确定它的外观。我对SQL没问题,但我对JOIN和UNION有点失望。 :-/
答案 0 :(得分:1)
您可以使用窗口功能来识别组。而且您可以在order by
中包括窗口函数,因此不需要子查询。
select *
from log_table l
order by max(case when l.operation = 'search' then l.log_date end) over (partition by l.name order by l.log_date),
l.name,
l.log_date;
Here是db <>小提琴。
答案 1 :(得分:0)
您可以使用条件lag()
调用来查找每个用户每个视图行的最新搜索日期/时间;搜索行获得自己的日期/时间:
-- CTE for sample data
with log_table (name, operation, log_date) as (
select 'john', 'search', timestamp '2019-01-01 13:00:00' from dual
union all select 'john', 'view', timestamp '2019-01-01 14:00:00' from dual
union all select 'john', 'view', timestamp '2019-01-01 15:00:00' from dual
union all select 'james', 'search', timestamp '2019-01-01 14:30:00' from dual
union all select 'james', 'view', timestamp '2019-01-01 15:15:00' from dual
union all select 'john', 'search', timestamp '2019-01-01 15:10:00' from dual
)
-- actual query
select name, operation, log_date,
case when operation = 'search' then log_date
else lag(case when operation = 'search' then log_date end ignore nulls)
over (partition by name order by log_date)
end as search_date
from log_table
order by log_date;
NAME OPERATION LOG_DATE SEARCH_DATE
----- --------- ------------------- -------------------
john search 2019-01-01 13:00:00 2019-01-01 13:00:00
john view 2019-01-01 14:00:00 2019-01-01 13:00:00
james search 2019-01-01 14:30:00 2019-01-01 14:30:00
john view 2019-01-01 15:00:00 2019-01-01 13:00:00
john search 2019-01-01 15:10:00 2019-01-01 15:10:00
james view 2019-01-01 15:15:00 2019-01-01 14:30:00
然后可以将其用作CTE或内联视图,并使用生成的search_date
进行排序,然后按实际记录日期对具有相同搜索日期的记录进行排序:
-- CTE for sample data
with log_table (name, operation, log_date) as (
select 'john', 'search', timestamp '2019-01-01 13:00:00' from dual
union all select 'john', 'view', timestamp '2019-01-01 14:00:00' from dual
union all select 'john', 'view', timestamp '2019-01-01 15:00:00' from dual
union all select 'james', 'search', timestamp '2019-01-01 14:30:00' from dual
union all select 'james', 'view', timestamp '2019-01-01 15:15:00' from dual
union all select 'john', 'search', timestamp '2019-01-01 15:10:00' from dual
)
-- actual query
select name, operation, log_date
from (
select name, operation, log_date,
case when operation = 'search' then log_date
else lag(case when operation = 'search' then log_date end ignore nulls)
over (partition by name order by log_date)
end as search_date
from log_table
)
order by search_date, log_date;
NAME OPERATION LOG_DATE
----- --------- -------------------
john search 2019-01-01 13:00:00
john view 2019-01-01 14:00:00
john view 2019-01-01 15:00:00
james search 2019-01-01 14:30:00
james view 2019-01-01 15:15:00
john search 2019-01-01 15:10:00
由于您可能会同时获得两个用户的搜索,因此您可能也希望将该用户包括在最终的order-by子句中:
...
order by search_date, name, log_date;