在SQL中从表中按顺序读取数值

3
我有以下表结构,它是根据用户界面的选择生成的,并按照生成时的顺序存储。这基本上是存储查询序列。
例如:
(( Condition AND Condition) OR ( Condition ))
ID ConditionType Value Brackets 1 NULL NULL ( 2 NULL NULL ( 3 NULL Condition NULL 4 AND NULL NULL 5 NULL Condition NULL 6 NULL NULL ) 7 OR NULL NULL 8 NULL NULL ( 9 NULL Condition NULL 10 NULL NULL ) 11 NULL NULL )
从上面的信息中,我需要生成一个索引:
ID StartIndex EndIndex 1 1 11 2 2 6 3 8 10
您有什么想法如何做到这一点?

6
请不要仅仅要求我们为您解决问题。请向我们展示您如何尝试自己解决问题,然后准确地展示结果,并告诉我们为什么您觉得它没有起作用。请参阅“你都尝试了什么?”这篇优秀的文章,您真的需要阅读一下。 - John Saunders
1
你的样本数据输入后,输出是如何产生的?可以给一些想法吗? - Ajay2707
2个回答

2

编辑:在第一版中,我忽略了嵌套级别。这个版本我已测试过 :)

我在DB2上工作,所以如果sql-server不支持LATERAL join,则可能需要重构此代码,但是在DB2上,使用您提供的值,此代码可以产生正确的结果:

with CTE_ONLY_BRACKETS as (
  select * 
  from   MYLIST 
  where  Brackets in('(',')')
) ,

CTE_NEST_INCREMENT as (
  select   Id
          ,Brackets
          ,case when Brackets = '(' then 1 else -1 end as NEST_INCREMENT
  from     CTE_ONLY_BRACKETS 
) ,

CTE_NEST_LEVEL as (
  select    Id
           ,Brackets
           ,S.NEST_LEVEL 
  from      CTE_NEST_INCREMENT C
  cross join lateral (
    select  sum( NEST_INCREMENT ) as NEST_LEVEL
    from    CTE_NEST_INCREMENT S
    where   S.Id <= C.Id
  ) as S

)

select   row_number() over() as Id
        ,L.Id as StartIndex
        ,R.Id as EndIndex
from     CTE_NEST_LEVEL R

cross join lateral (
  select L.Id
  from   CTE_NEST_LEVEL L
  where  L.Brackets = '('
    and  L.Id < R.Id
    and  L.NEST_LEVEL = R.NEST_LEVEL + 1
  order by L.Id desc
  fetch  first row only
) as L

where    R.Brackets = ')'

order by L.Id

您的查询在 Sql Server 中也可以正常执行。它的输出结果是 (1, 1, 11), (2, 2, 10), (3, 8, 6)。我认为这不是期望的结果。 - Giorgos Betsos
有趣。哪个DB2版本支持Lateral Join? - user330315
我在System i上的DB2版本V7R1上工作,支持lateral joins。 - Mike Jones
如果其他平台上的最新版本的DB2不支持Lateral Join,我会感到惊讶。在查询功能方面,System i上的DB2往往落后于其他平台,但在自动驾驶方面领先于其他平台,并且需要较少的手动管理。附言:对于SQL-SERVER,请删除“仅获取第一行”引用,并在同一连接查询中将“select L.Id”替换为“select top 1 L.Id”。快速的谷歌搜索让我认为CROSS APPLY是SQL-SERVER中LATERAL JOIN的等效物。 - Mike Jones
如果CROSS APPLY不能很好地替代LATERAL连接,另一种选择是删除这些LATERAL连接,并在select列列表中使用子查询。 - Mike Jones

0
你可以试试这个。
DECLARE @SampleDate TABLE (Id INT, ConditionType VARCHAR(10), Value VARCHAR(10), Brackets VARCHAR(10))
INSERT INTO @SampleDate VALUES
(  1, NULL , NULL           , '('),
(  2, NULL , NULL           , '('),
(  3, NULL , 'Condition'    , NULL),
(  4, 'AND', NULL           , NULL),
(  5, NULL , 'Condition'      , NULL), 
(  6, NULL , NULL           , ')'),
(  7, 'OR' , NULL           , NULL),
(  8, NULL , NULL           , '('),
(  9, NULL , 'Condition'    , NULL),
( 10, NULL , NULL           , ')'),
( 11, NULL , NULL           , ')')

;WITH CTE AS (
    SELECT * FROM @SampleDate T1 
        OUTER APPLY ( SELECT SUM (CASE 
                            WHEN Brackets = '(' THEN 1 WHEN Brackets = ')' THEN -1 ELSE 0 END) Inx 
                FROM @SampleDate T2
                WHERE T1.Id >= T2.Id ) X
)
SELECT 
    ROW_NUMBER() OVER(ORDER BY X1.Id) AS Id,
    X1.Id StartIndex, 
    T.Id EndIndex 
FROM CTE X1
OUTER APPLY (SELECT TOP 1 * FROM CTE X2 
                WHERE X2.Brackets =')' AND X2.Id > X1.Id AND X2.Inx = X1.Inx - 1 ORDER BY X2.Id ) AS T
WHERE 
    X1.Brackets ='('

结果:

Id                   StartIndex  EndIndex
-------------------- ----------- -----------
1                    1           11
2                    2           6
3                    8           10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接