2013-10-18 36 views
0

我来SQL有很多必要的经验,并试图弄清楚如何做到感觉它需要一个没有SQL循环的循环。也就是说,在SQL中循环使用命令式语言时,什么是不循环的习惯用法?如何不在SQL中循环使用集合

我在SQL(服务器)的表像这样(假设我们选择其中的标签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伪代码,并假设某种类型的数据库连接处理类的,我这样做:

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的方式是什么?

答:

短版:热膨胀系数与连接

长版(其中有些可能是不必要的):

-- 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 

回答

1

我通常CTE打破了问题:■

WITH FirstZeroIndex AS (
    SELECT Tag_Id 
      ,MIN(inc_indx) AS ZeroIdx 
    FROM mytable 
    WHERE State = 0 
    GROUP BY Tag_Id 
) 
,LastNonZeroIndex AS (
    SELECT mytable.Tag_Id 
      ,MAX(mytable.inc_indx) AS NonZeroIdx 
    FROM mytable 
     LEFT JOIN FirstZeroIndex 
      ON myTable.Tag_Id = FirstZeroIndex.Tag_Id 
    WHERE FirstZeroIndex.ZeroIdx IS NULL -- If we want tags without zeros 
      OR mytable.inc_indx < FirstZeroIndex.ZeroIdx 
    GROUP BY mytable.Tag_Id 
) 
SELECT * 
FROM LastNonZeroIndex 
WHERE Tag_id = 999 
+0

我想我解释自己做得不好。我已更新。 – anthropomo

+0

不完全是答案,但这让我在那里。 – anthropomo

1

如何使用申请?毫无疑问,有一些其他的方式,但是这一个工程

select q1.* 
from mytable as q1 
cross apply (
    select top 1 * 
    from mytable as q2 
    where q2.Tag_Id = q1.Tag_Id 
     and q2.State = 0 
     and q2.inc_indx > q1.inc_indx 
    order by q2.inc_indx desc 
) as q2 

这是我使用的模式/数据

CREATE TABLE mytable (
    inc_indx int, 
    State int, 
    Tag_Id int 
) 

insert into mytable 
values 
    (1, 5, 999), 
    (2, 3, 998), 
    (3, 0, 999), 
    (4, 50, 991), 
    (5, 39, 989), 
    (6, 0, 991) 

编辑:

从我从你的榜样理解好和伪代码,是一个标签可以有多个状态(包括0),并且你想要一个特定标签之前的0状态之前的状态? Like so?

+0

这似乎是最后的零,在这里我想每个前0 – anthropomo

+0

你是什么意思的,以获得最后的值之前得到的一切最后的价值?你想要哪一列?而不是'SELECT *'你能不能只选择你想要的列? – Umair

+0

这产生了“上一次状态= 0之前的所有行”。我想要“State = 0之前的每一行,每个State = 0在初始集合中”。 – anthropomo