如何根据该行的条件在表格行的每个给定数字之间获取下一个可用数字

How to get next available number between given numbers for each of the table row based on condition of that row

提问人:Raghu 提问时间:11/15/2023 更新时间:11/16/2023 访问量:32

问:

对于从 Oracle DB 表中获取的每个 Product 记录,我需要在给定的数字范围之间生成下一个可用数字。在生成下一个数字时,只要给定数字范围内有未使用的号码可用,就不涉及条件检查。当它已经达到给定数字范围内的最后一个数字时,它应该从头开始重复,但从这个时候开始,它应该根据条件检查生成它。

我将尝试以一种简单的方式表达我的要求。

要使用的序列号范围:1-3(1 到 3)

PRODUCT 表中的数据:

Name  Start Date    End Date
P1    1-Nov
P2    1-Nov         5-Nov
P3    1-Nov
P4    2-Nov
p2    2-Nov

假设没有结束日期的产品是有效产品,具有结束日期的产品是非活动产品。

预期输出:

Name  Start Date    End Date    SequenceNumber     Comment
P1    1-Nov                     1                  No conditional check
P2    1-Nov         5-Nov       2                  No conditional check
P3    1-Nov                     3                  No conditional check
P4    2-Nov                     2                  Sequence should start from 1 again but with condition check while generating sequence. Condition: If the generated number is used in any other active product, move on to next number  
p2    2-Nov                                        In this case, all 1, 2, 3 are mapped to active products. so no sequence is generated.

问题: 如何使用 select 语句获得所需的输出?这将是有帮助的,你可以就此提出一些建议。谢谢。

SQL 预言机

评论

0赞 Raghu 11/15/2023
1.) “预期输出”下提到的第 4 行的附加说明:由于我们已经完成了给定范围内所有序列号的使用,因此它尝试从 1 开始。但是,我们的序列号“1”已被活动产品“P1”使用。因此,它使用下一个序列号“2”作为产品“P4”。2.) 给定的数字范围不必是动态的。在我的实际场景中,应该使用从 1 到 6 的数字。

答:

0赞 d r 11/16/2023 #1

嗯,它看起来像行间 - 列间处理,这意味着您可以使用 Oracle 的 MODEL 子句。它的工作原理很像处理单个单元格的 excel 工作表。

WITH    --  S a m p l e   D a t a :
    tbl AS
        (   Select 'P1' "A_NAME",  Date '2023-11-01' "START_DATE", Null "END_DATE" From Dual Union All
            Select 'P2' "A_NAME",  Date '2023-11-01' "START_DATE", Date '2023-11-05' "END_DATE" From Dual Union All
            Select 'P3' "A_NAME",  Date '2023-11-01' "START_DATE", Null "END_DATE" From Dual Union All
            Select 'P4' "A_NAME",  Date '2023-11-02' "START_DATE", Null "END_DATE" From Dual Union All
            Select 'P2' "A_NAME",  Date '2023-11-02' "START_DATE", Null "END_DATE" From Dual 
        )
--  M a i n    S Q L :
SELECT    A_NAME, START_DATE, END_DATE, SEQUENCE_NUMBER
FROM    ( Select  ROWNUM "RN", A_NAME, START_DATE, END_DATE, 0 "SEQUENCE_NUMBER"
          From    tbl
        )
             -- RowNum (RN) used to uniquely identify rows
        MODEL   Dimension By ( RN )
                Measures ( A_NAME, START_DATE, END_DATE, SEQUENCE_NUMBER, 0 "SEQUENCES" )
        RULES
            ( SEQUENCE_NUMBER[ANY] =  Case When   Case  When Nvl(Count(START_DATE)[RN < CV()], 0) + 1 <= 3 
                                                        Then Nvl(Count(START_DATE)[RN < CV()], 0) + 1 
                                                  Else 0 End = 0
                                              Then  0
                                      Else   Case When Nvl(Count(START_DATE)[RN < CV()], 0) + 1 <= 3 
                                                  Then Nvl(Count(START_DATE)[RN < CV()], 0) + 1   -- this gives non conditional sequences (1 - 3)
                                             Else 0 End
                                      End,
                  --
               -- added colummn SEQUENCES to control the sequence numbers used before the current row
                  SEQUENCES[ANY] = Nvl(Max(SEQUENCE_NUMBER)[RN < CV(RN)], 0),
                  --
                  SEQUENCE_NUMBER[ANY] = Case When SEQUENCE_NUMBER[CV()] = 0
                                              Then Case When SEQUENCES[CV()] = 3 And 
                                                             Min(SEQUENCE_NUMBER)[RN < CV()] = 1 And
                                                             Max(SEQUENCES)[RN < CV()] < 3
                                                        Then Min(SEQUENCE_NUMBER)[RN < CV()] + 1  -- this gives conditional sequence when first is used (used + 1)
                                                   End  -- no Else part (same as Else Null) gives Null when (used + 1) is also done
                                         Else SEQUENCE_NUMBER[CV()]
                                         End
                )
/*    R e s u l t :
A_NAME START_DATE END_DATE  SEQUENCE_NUMBER                            
------ ---------- --------- --------------- 
P1     01-NOV-23                          1 
P2     01-NOV-23  05-NOV-23               2 
P3     01-NOV-23                          3 
P4     02-NOV-23                          2 
P2     02-NOV-23                             */