我有一张这样的表
+--------------------------------------------+
|id(autoincr)|session_id |attmpt_counter|
+------------+----------------+--------------+
|0 |ses0 |0 |
|1 |ses0 |1 |
|2 |ses1 |0 |
|3 |ses1 |1 |
|4 |ses1 |1 |
|5 |ses1 |2 |
|6 |ses1 |3 |
|7 |ses2 |0 |
|8 |ses2 |0 |
|9 |ses2 |0 |
+------------+----------------+--------------+
对于窗口(按try_counter按session_id顺序分区)我希望通过以下数学进入:如果行'attempt_counter'的下一个值不大于先前值,则递增。 我想在没有函数的情况下得到一个累积此规则的表(尽可能使用row cross-rdbms sql)
+--------------------------------------------+---------------+
|id(autoincr)|session_id |attmpt_counter|entrance |
+------------+----------------+--------------+---------------+
|0 |ses0 |0 |0 |
|1 |ses0 |1 |0 |
|2 |ses1 |0 |0 |
|3 |ses1 |1 |0 |
|4 |ses1 |1 |1 |
|5 |ses1 |2 |1 |
|6 |ses1 |3 |1 |
|7 |ses2 |0 |0 |
|8 |ses2 |0 |1 |
|9 |ses2 |0 |2 |
+------------+----------------+--------------+---------------+
欢迎任何建议。
答案 0 :(得分:1)
使用分析(windows)函数很容易:
SELECT id, session_id,ATTMPT_COUNTER,
sum( ATTMPT_COUNTER2 ) over (partition by session_id order by id ) as accumulating
FROM (
select id, session_id,ATTMPT_COUNTER,
case ATTMPT_COUNTER
when lag( ATTMPT_COUNTER ) over (partition by session_id order by id )
then 1 else 0
end As ATTMPT_COUNTER2
from table1 t
)
order by id
;
如果您不喜欢Windows功能,请尝试以下操作:
WITH subquery AS (
SELECT id, session_id,ATTMPT_COUNTER,
case ATTMPT_COUNTER
when ( SELECT ATTMPT_COUNTER FROM table1 t1
WHERE t1.session_id = t.session_id
AND t1.id < t.id
ORDER BY id DESC
FETCH first row only
)
then 1 else 0 end as ATTMPT_COUNTER2
FROM table1 t
)
SELECT s1.id, s1.session_id, sum( s2.ATTMPT_COUNTER2 ) as accumulating
FROM subquery s1
JOIN subquery s2
ON s1.session_id = s2.session_id AND s1.id >= s2.id
GROUP BY s1.id, s1.session_id
order by id
如果您也不喜欢WITH子句(公用表表达式),则必须以这种方式复制子查询:
SELECT s1.id, s1.session_id, sum( s2.ATTMPT_COUNTER2 ) as accumulating
FROM (
SELECT id, session_id,ATTMPT_COUNTER,
case ATTMPT_COUNTER
when ( SELECT ATTMPT_COUNTER FROM table1 t1
WHERE t1.session_id = t.session_id
AND t1.id < t.id
ORDER BY id DESC
FETCH first row only
)
then 1 else 0 end as ATTMPT_COUNTER2
FROM table1 t
)s1
JOIN (
SELECT id, session_id,ATTMPT_COUNTER,
case ATTMPT_COUNTER
when ( SELECT ATTMPT_COUNTER FROM table1 t1
WHERE t1.session_id = t.session_id
AND t1.id < t.id
ORDER BY id DESC
FETCH first row only
)
then 1 else 0 end as ATTMPT_COUNTER2
FROM table1 t
) s2
ON s1.session_id = s2.session_id AND s1.id >= s2.id
GROUP BY s1.id, s1.session_id
order by id
FETCH first row only
子句(ANSII SQL变体)适用于Oracle 12c和DB2,其他数据库使用LIMIT 1
子句(不符合ANSII SQL)。
答案 1 :(得分:0)
使用LAG
和SUM
分析函数:首先检查前一行的尝试计数器是否大于当前行的计数器;然后总计每个会话的当前行和所有先前行的访问次数。
SELECT id,
session_id,
attmpt_counter,
SUM( has_accessed ) OVER ( PARTITION BY session_id ORDER BY id ) AS entrance
FROM (
SELECT t.*,
CASE
WHEN LAG( attmpt_counter ) OVER ( PARTITION BY session_id ORDER BY id )
>= attmpt_counter
THEN 1
ELSE 0
END AS has_accessed
FROM table_name t
);