如何从数据库检索堆栈

时间:2019-11-05 03:36:11

标签: database sqlite

我有一个名为“ Stack”的表。

Foo

我想找出Stack_Counter'20'中的堆栈数组。

所以正确答案应该是

+---------------+-------+-------------+
| Stack_Counter | value | Stack_Depth |
+---------------+-------+-------------+
|             1 |     3 |           1 |
|             2 |     0 |           2 |
|             3 |     0 |           1 |
|             4 |       |           0 |
|             5 |     3 |           1 |
|             6 |     3 |           2 |
|             7 |     1 |           3 |
|             8 |     2 |           2 |
|             9 |     4 |           1 |
|            10 |     2 |           2 |
|            11 |     0 |           3 |
|            12 |     0 |           2 |
|            13 |     0 |           1 |
|            14 |     2 |           2 |
|            15 |     2 |           3 |
|            16 |     1 |           4 |
|            17 |     1 |           3 |
|            18 |     2 |           2 |
|            19 |     1 |           3 |
|            20 |     0 |           4 |
+---------------+-------+-------------+

基本上,这是找出所选Stack_Depth中的连续行。

有什么办法可以实现?

3 个答案:

答案 0 :(得分:1)

...这是通用的全SQL解决方案:

SELECT Stack_Counter, value, Stack_Depth 
FROM
  (SELECT *, RANK() OVER (
      PARTITION BY Stack_Depth
      ORDER BY Stack_Counter DESC) rank
   FROM stack)
WHERE rank=1 AND Stack_Depth > 0;

答案 1 :(得分:0)

仅使用SQL的解决方案可能比其价值更大的麻烦(由于其复杂性或乏味性),但这是与SQLite一起使用的解决方案:

SELECT * FROM (SELECT * FROM stack WHERE Stack_Depth=1 ORDER BY Stack_Counter DESC LIMIT 1)
UNION ALL
SELECT * FROM (SELECT * FROM stack WHERE Stack_Depth=2 ORDER BY Stack_Counter DESC LIMIT 1)
UNION ALL
SELECT * FROM (SELECT * FROM stack WHERE Stack_Depth=3 ORDER BY Stack_Counter DESC LIMIT 1)
UNION ALL
SELECT * FROM (SELECT * FROM stack WHERE Stack_Depth=4 ORDER BY Stack_Counter DESC LIMIT 1);

答案 2 :(得分:-1)

在我自己的评论中,我在注释中提到的窗口函数比我想象的要困难得多。 Peak的答案是使用rank()窗口函数的优雅解决方案,这正是我最初想要的。同时,sqlite还支持recursive CTE(公用表表达式; WITH语句):

WITH RECURSIVE
     latest (id, level) AS (
          VALUES (20, (SELECT Stack_Depth FROM stack WHERE Stack_Counter = 20))
          UNION ALL
          SELECT (SELECT max(Stack_Counter) 
                  FROM stack
                  WHERE Stack_Depth = level - 1
                        AND Stack_Counter <= 20),
                  level - 1
          FROM latest
          WHERE level - 1 > 0
     )
SELECT stack.*
FROM stack INNER JOIN latest
     ON stack.Stack_Counter = latest.id
ORDER BY stack.Stack_Counter

我必须在三个位置插入所需的堆栈级别,但是如果您从宿主语言中的准备好的语句调用此参数,则可以用命名的SQL参数替换所有这些位置。

如果您对选择特定的Stack_Counter值不感兴趣,而只是希望从整个表中获取结果,则将VALUES子句替换为SELECT之类的

WITH RECURSIVE
     latest (id, level) AS (
          SELECT * FROM (SELECT Stack_Counter, Stack_Depth FROM stack ORDER BY Stack_Counter DESC LIMIT 1)
          UNION ALL
          SELECT (SELECT max(Stack_Counter) 
                  FROM stack
                  WHERE Stack_Depth = level - 1),
                  level - 1
          FROM latest
          WHERE level - 1 > 0
     )
SELECT stack.*
FROM stack INNER JOIN latest
     ON stack.Stack_Counter = latest.id
ORDER BY stack.Stack_Counter