使用基于日期的条件的连续值替换历史代码中的第一个非零数字的 SQL 查询

问题描述 投票:0回答:1

我正在处理包含嵌套选择语句的 SQL 查询。我需要修改它,以便根据某些条件,将“历史代码”中右侧的第一个非零值替换为一系列连续数字。

例如,如果历史代码是0302230,我想将其转换为0302232100。在这个例子中,3(右侧第一个非零值)被替换为3210,结果是03022(3210)0 .

历史代码逻辑取决于涉及两个日期的条件:paidAt和deadlineDate。 根据历史代码中第一个非零出现的值进行转换。逻辑总结如下:

如果右侧第一个非零数字是 1,则将其替换为 10。 如果是2,则替换为210。 如果是 3,则将其替换为 3210,依此类推,直至: 如果是6,则替换为6543210。 如果是W,则更换为W6543210。 并附加其余的历史代码

下面是我当前正在使用的 SQL 代码:


SELECT

GROUP_CONCAT(

CASE

WHEN i.paidAt IS NULL

AND DATE_ADD(i.deadlineDate, INTERVAL 10 DAY) < CURDATE()

AND i.dueDate = (

SELECT MIN(i2.dueDate)

FROM installment i2

WHERE i2.contractId = i.contractId

AND i2.paidAt IS NULL

AND DATE_ADD(i2.deadlineDate, INTERVAL 10 DAY) < CURDATE()

LIMIT 1

)

THEN

CASE

WHEN DATEDIFF(CURDATE(), DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) <= 0 THEN '0'

WHEN DATEDIFF(CURDATE(), DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 1 AND 29 THEN '1'

WHEN DATEDIFF(CURDATE(), DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 30 AND 59 THEN '2'

WHEN DATEDIFF(CURDATE(), DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 60 AND 89 THEN '3'

WHEN DATEDIFF(CURDATE(), DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 90 AND 119 THEN '4'

WHEN DATEDIFF(CURDATE(), DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 120 AND 149 THEN '5'

WHEN DATEDIFF(CURDATE(), DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 150 AND 179 THEN '6'

WHEN DATEDIFF(CURDATE(), DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) >= 180 THEN 'W'

END

ELSE

CASE

WHEN DATEDIFF(i.paidAt, DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) <= 0 THEN '0'

WHEN DATEDIFF(i.paidAt, DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 1 AND 29 THEN '1'

WHEN DATEDIFF(i.paidAt, DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 30 AND 59 THEN '2'

WHEN DATEDIFF(i.paidAt, DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 60 AND 89 THEN '3'

WHEN DATEDIFF(i.paidAt, DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 90 AND 119 THEN '4'

WHEN DATEDIFF(i.paidAt, DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 120 AND 149 THEN '5'

WHEN DATEDIFF(i.paidAt, DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) BETWEEN 150 AND 179 THEN '6'

WHEN DATEDIFF(i.paidAt, DATE_ADD(i.deadlineDate, INTERVAL 10 DAY)) >= 180 THEN 'W'

END

END ORDER BY i.dueDate DESC SEPARATOR ''

)

FROM installment i

WHERE i.contractId = [c.id](http://c.id/)

) AS 'Payment History Status Code',

有人可以帮我实现正确替换历史代码中右侧第一个非零值的逻辑吗?

                           r  
sql mysql database table-plus
1个回答
0
投票

你有 REGEXP_INSTR 吗?:

SELECT id, Historycode, char_length(HistoryCode),TargetCharPos,
   case substring(HistoryCode, TargetCharPos , 1)
         when '0' then HistoryCode
         else concat(
                left(HistoryCode, TargetCharPos-1),
                case substring(HistoryCode, TargetCharPos , 1)
                  when '1' then '10'
                  when '2' then '210'
                  when '3' then '3210'
                  when '6' then '6543210'
                end,
                substring(HistoryCode,TargetCharPos+1)
            )
           end as NewHistoryCode
from ( SELECT id, Historycode, REGEXP_INSTR(HistoryCode, '[^0]0*$') as TargetCharPos FROM Tbl
      ) Step1

我们找到子查询中最后一个非零字符位置,然后在另一个查询中计算出替换值。

© www.soinside.com 2019 - 2024. All rights reserved.