我在 SQLite 中对 Codility / 练习 6 SQL / SqlEventsDelta 的解决方案适用于本地数据库浏览器,但不适用于在线 Codility 测试编辑器。我该如何解决这个问题?我想使用我自己的 SQLite 代码:
WITH cte1 AS
(
SELECT *, CASE WHEN e2.event_type = e2.prev THEN 0
WHEN e2.event_type = e2.next THEN 0
ELSE 1 END AS grp
FROM (SELECT *, LAG(e1.event_type) OVER(ORDER BY (SELECT 1)) AS prev , LEAD(e1.event_type) OVER(ORDER BY (SELECT 1)) AS next FROM events e1) e2
)
,cte2 AS
(
SELECT cte1.event_type, cte1.time, cte1.grp, cte1.value - LAG(cte1.value) OVER(ORDER BY cte1.event_type, cte1.time) AS value
FROM cte1
WHERE cte1.grp = 0
ORDER BY cte1.event_type, cte1.time
)
SELECT c2.event_type, c2.value
FROM cte2 c2
WHERE (c2.event_type, c2.time) IN (
SELECT c2.event_type, MAX(c2.time) AS time
FROM cte2 c2
GROUP BY c2.event_type)
GROUP BY c2.event_type
ORDER BY c2.event_type, c2.time
它在 DB Browser for SQLite Version 3.12.2 上运行,没有错误:
event_type | value
-----------+-----------
2 | -5
3 | 4
Execution finished without errors.
Result: 2 rows returned in 7ms
但是在 Codility 测试编辑器(SQLite 版本 3.11.0)上我收到错误:
| Compilation successful.
| Example test: (example test)
| Output (stderr):
| error on query: ...
| ...
| ...,
| details: near "(": syntax error
| RUNTIME ERROR (tested program terminated with exit code 1)
Detected some errors.
我尝试使用一种有点幼稚的方法。我知道由于有很多子查询,这对性能非常不利,但这里的问题是 PostgreSQL 的“DISTINCT ON”,但我得到了 100% 😃
希望你喜欢!
select distinct on (event_type) event_type, result * -1
from (select event_type, value, lead(value) over (order by event_type) - value result
from (select *
from events
where event_type in (select event_type
from events
group by event_type
having count(event_type) >= 2)
order by event_type, time desc) a) b
with data as (SELECT a.event_type, a.value, a.time,
--Produce a virtual table that stores the next and previous values for each event_type.
LEAD(a.value,1) over (PARTITION by a.event_type ORDER by 'event_type', 'time' DESC) as recent_val,
LAG(a.value,1) over (PARTITION by a.event_type ORDER by 'event_type', 'time' DESC) as penult_val
from events a
JOIN (SELECT event_type
from events --Filter the initial dataset for duplicates. Store in correct order
group by event_type HAVING COUNT(*) > 1
ORDER by event_type) b
on a.event_type = b.event_type) --Compare the virtual table to the filtered dataset
SELECT event_type, ("value"-"penult_val") as diff --Perform the desired arithematic
from data
where recent_val is NULL --Filter for the most recent value
嗨,团队!这就是我的答案。它很大程度上是上述答案的混合体,但它读起来更简单,并且针对上下文进行了评论。作为一个新手,希望对其他新手有帮助。
with deltas as (
select distinct event_type,
first_value(value) over (PARTITION by event_type ORDER by time DESC) -
nth_value(value, 2) over (PARTITION by event_type ORDER by time DESC) as delta
from events
)
select * from deltas where delta is not null order by 1;
我在使用sqlite时也遇到同样的问题。 尝试在 PostgreSQL 中使用以下代码
with data as (select
e.event_type,
e.value,
e.time,
lead(e.value,1) over (PARTITION by e.event_type order by e.event_type,e.time asc) as next_val,
lag (e.value,1) over (PARTITION by e.event_type order by e.event_type,e.time asc) as prev_val
from events e)
select distinct d.event_type, (d.value-d.prev_val) as diff
from
events e,data d
where e.event_type = d.event_type
and d.next_val is null
and e.event_type in ( SELECT event_type
from data
group by
event_type
having count(1) > 1)
order by 1;
添加另一个涉及自连接的答案 -
-- write your code in PostgreSQL 9.4
WITH TotalRowCount AS (
SELECT
event_type,
COUNT(*) as row_count
FROM events
GROUP BY 1
),
RankedEventType AS (
SELECT
event_type,
value,
ROW_NUMBER() OVER(PARTITION BY event_type ORDER BY time) as row_num
FROM events
)
SELECT
a.event_type,
a.value - b.value as value
FROM RankedEventType a
INNER JOIN TotalRowCount c
ON a.event_type = c.event_type
INNER JOIN RankedEventType b
ON a.event_type = b.event_type
WHERE 1 = 1
AND a.row_num = c.row_count
AND b.row_num = c.row_count - 1
ORDER BY 1
没有嵌套查询,获得100%
with data as (
with count as (select event_type
from events
group by event_type
having count(event_type) >= 2)
select e.event_type , e.value, e.time from events as e inner join count as r on e.event_type=r.event_type order by e.event_type, e.time desc
)
select distinct on (event_type) event_type,
value - (LEAD(value) over (order by event_type)) result from data
一个子查询的解决方案
WITH diff AS
(SELECT event_type,
value,
LEAD(value) OVER (PARTITION BY event_type
ORDER BY TIME DESC) AS prev
FROM EVENTS
GROUP BY event_type,
value,
time
)
SELECT DISTINCT ON (event_type) event_type,
value - prev
FROM diff
WHERE prev IS NOT NULL;
--在 PostgreSQL 9.4 中
with ct1 as (SELECT
event_type,
value,
time,
rank() over (partition by event_type order by time desc) as rank
from events),
ct2 as (
select event_type, value, rank, lag (value,1) over (order by event_type) as previous_value
from ct1
order by event_type)
select event_type, previous_value - value from ct2
where rank = 2
order by event_type
--1) “极简”旧式解决方案(不使用窗口函数)
WITH maxevents AS(选择 event_type 作为 Et1,max(time) 作为 maxtime from events
按 event_type 进行分组,其中 count(1)>1),
防止 AS(选择 event_type 作为 Et2,max(time) 作为 nextime
来自事件 JOIN maxevents ON event_type=Et1 AND time
选择 event_type,v1-v2 作为值
FROM maxeventvalues JOIN preveventvalues ON event_type=et
按 event_type asc 排序
;
--2) 使用窗口函数的现代解决方案
WITH maxevents AS(选择 event_type 为 Et1,max(time) 为 maxtime
来自按 event_type 划分的事件组,其中 count(1)>1)
,AllValDifs as (SELECT event_type, value-
LAG(value,1,0) OVER (PARTITION BY event_type ORDER BY time ASC) as ValDif , time
FROM 事件 JOIN maxevents ON event_type=et1)
选择不同的事件类型,FIRST_VALUE(ValDif)
来自 AllValDifs 的 OVER (PARTITION BY event_type ORDER BY time DESC)
按事件类型 ASC 排序;
我的解决方案:
通过
event_type
获取排名1、2的表格:
with t2 as(
select event_type, value, rank from (
select event_type, value,
rank() over(
partition by event_type
order by time desc) as rank,
count(*) over (partition by event_type) as count
from events) as t
where t.rank <= 2 and t.count > 1
)
使用
Lead()
计算差异并使用max
过滤掉空差异:
select t3.event_type, max(t3.diff) from (
select event_type,
value - lead(value, 1) over (
partition by event_type
order by rank) as diff
from t2) as t3
group by t3.event_type
我在 MSSQL 上尝试了这个,它也有效
SELECT event_type,
MAX(value) - MAX(prev_value) AS value_difference
FROM (
SELECT event_type,
value,
L.AG(value) OVER (PARTITION BY event_type ORDER BY time) AS prev_value
FROM events) AS subquery
GROUP BY event_type
HAVING COUNT(*) > 1
ORDER BY event_type;
我能够用这种方式解决它:
select
event_type
,delta
from (
select
*
,rn_calc - lead(value) over(partition by event_type order by rn asc) delta
from (
select
event_type
,max(value) over(partition by event_type order by time desc) rn_calc
,row_number() over(partition by event_type order by time desc) rn
,value
--,time
from events
) t
where rn in (1,2)
) t
where rn = 1 and delta is not null
这可以简单地通过
来完成WITH ranked_event AS (
SELECT
event_type,
value,
time,
ROW_NUMBER() OVER (PARTITION BY event_type ORDER BY time DESC) AS row_num
FROM events
)
SELECT
e1.event_type,
e1.value - e2.value AS value_difference
FROM ranked_event AS e1
INNER JOIN ranked_event AS e2
ON e1.event_type = e2.event_type
AND e1.row_num = 1 AND e2.row_num = 2
ORDER BY e1.event_type