在多个ID之前选择行

时间:2012-09-03 10:22:58

标签: sql database sqlite union

我希望在具有指定值的行之前获得2行ID。

所以我在表格中有ID和值

ID   value
1,   x
3,   x 
7,   x
8,   error
9,   x
10.  x
11,  x
12   error

我想要错误之前的两行。

我可以使用硬编码错误行ID

执行此操作
SELECT id FROM thetable WHERE id < 8 ORDER BY ID DESC LIMIT 2  
UNION ALL
SELECT id FROM thetable WHERE id < 12 ORDER BY ID DESC LIMIT 2

我怎么不能对错误ID进行硬编码,如何将其与SELECT id FROM thetable WHERE value = 'error'或其他任何方式结合使用?

我使用的是sqlite 3,但我对所有内容感兴趣。

4 个答案:

答案 0 :(得分:3)

我是SQLite的新手,所以我不知道它的语法和所有。但如果它适用于你,请尝试下面的代码

select id,value
from (select *,rowid rid from tbl
order by id)
where rid in
(
  select rowid-1 from tbl
  where value = 'error'
  order by id
)or rid in
(
  select rowid-2 from tbl
  where value = 'error'
  order by id
)

<强> DEMO

答案 1 :(得分:2)

SQL Fiddle Demo


我不知道sqllite是否具有排名功能,这会使解决方案变得更容易,但是后续语句应该适用于任何符合ANSI-92的DBMS。

解决方案的要点是

  • 第1步:获取所有error ID
  • 第二步:获取所有ID&lt;通过使用GROUP BY子句并使用相同的查询连接来检索原始错误ID
  • 的根ID
  • 步骤3:与第二步类似,但是下降另一个级别。

SQL声明

SELECT  ID
FROM    (
              -- Select the ROOT value
              SELECT  ID, 0 AS GroupID
              FROM    thetable
              WHERE   value = 'error'
              UNION ALL

              -- Selects the ROOT value - 1 
              SELECT  MAX(t.ID) AS ID, te.ID AS GroupID
              FROM    thetable AS t
                      INNER JOIN (
                        SELECT  ID
                        FROM    thetable
                        WHERE   value = 'error'
                      ) AS te ON te.ID > t.ID 
              GROUP BY
                      te.ID

              UNION ALL        

              -- Selects the ROOT value - 1 - 1 
              SELECT  MAX(t.ID), te.ID
              FROM    thetable AS t
                      INNER JOIN (        
                        SELECT  MAX(t.ID) AS ID, te.ID AS GroupID
                        FROM    thetable AS t
                                INNER JOIN (
                                  SELECT  ID
                                  FROM    thetable
                                  WHERE   value = 'error'
                                ) AS te ON te.ID > t.ID 
                        GROUP BY
                                te.ID
                      ) AS te ON te.ID > t.ID
              GROUP BY
                      te.ID
            ) AS t                  

ORDER BY
        ID

修改

FWIW:如果SQLite允许排名函数和cte,则以下语句返回相同的结果,但更加精简。

;WITH q AS (
  SELECT  ROW_NUMBER() OVER (ORDER BY ID) rn
          , ID
          , value
  FROM    thetable 
)
SELECT  q2.ID
FROM    q q1
        INNER JOIN q q2 ON q2.rn BETWEEN q1.rn - 2 AND q1.rn
WHERE   q1.value = 'error'

答案 2 :(得分:0)

select id, value 
from test where id in (select id-1 from test where value = 'error')

如果您总是在查找错误背后的第一个ID,这将有效。如果您可以跳过id,则可以使用MIN函数来获取最接近的现有ID。

答案 3 :(得分:0)

试试这个:

SELECT id 
FROM thetable 
ORDER BY 
   CASE WHEN value = 'error' THEN value ELSE ID END
 DESC