我带着大量的命令式经验来到 SQL,并试图弄清楚如何做感觉它需要一个循环而不需要 SQL 中的循环。即,在您绝对会在命令式语言中循环的情况下,不循环 SQL 的惯用方法是什么?
我在 SQL (Server) 中有一个类似这样的表(假设我们选择标签 ID 为 999 的位置,并且 inc_indx 是自动递增的)
inc_indx | State | Tag_Id
400 5 999
399 3 "
397 0 "
395 50 "
392 39 "
...etc
本质上,状态会增加一段时间,然后不可预测地为零。我想获得给定集合中每个零值之前的最后一个值。
要这样做一次,我会这样做:
SELECT TOP 1 [State]
FROM [mytable]
WHERE [inc_indx] <
(SELECT TOP 1 [inc_ndx]
FROM [mytable]
WHERE Tag_Id = 999
AND State = 0)
AND Tag_Id = 999
要重复执行此操作,在命令式 pythonish 伪代码中并假设某种类型的 DB 连接处理类,我会这样做:
setOfZeroes = handler.query("SELECT [inc_ndx]
FROM [mytable]
WHERE Tag_Id = 999
AND State = 0")
setOfMaxes = []
for index in setOfZeroes:
max = handler.query("SELECT TOP 1 [State]
FROM [mytable]
WHERE [inc_indx] < "
+ index +
" AND Tag_Id = 999")
setOfMaxes.add(max)
但是,假设我想在 SQL 中完成这一切并且我不想循环,那么 SQLese 的方法是什么?
回答:
简短版本:CTE 和联接
长版(其中一些可能是不必要的):
-- narrow the scope, add a numbered row
WITH numbered AS (SELECT [State]
,inc_indx
,ROW_NUMBER() OVER (Order by inc_indx) As [row]
FROM mytable
WHERE Tag_Id = 999)
-- put the row numbers where state is zero in a second CTE
, zeroes AS (SELECT [row]
FROM numbered
WHERE State = 0)
SELECT [State], [inc_indx]
FROM numbered, zeroes
WHERE numbered.[row] = zeroes.[row] - 1
ORDER BY [inc_indx] desc