oracle 使用查询对队列中的条目进行重新排序的更好方法是什么

fnx2tebb  于 2023-08-04  发布在  Oracle
关注(0)|答案(1)|浏览(81)

Oracle 19
我有一个进程,门票在队列中排序,各种进程可以从队列中添加和删除项目,我不完全相信写入队列的代码不会重复排名,所以我需要一种方法来定期重新排序队列。我有一个工作查询,但只是想知道是否有更好的方法来做。
表的重要部分:
ticket_id number(10)表的主键
queue_rank number(3)票证的等级,如果不在队列中,则为null
ticket_state varchar2(32)条目的当前状态,'Queued'是queue_rank唯一重要的状态
create_date date duh
我正在运行的查询是:

UPDATE  ticket_detail TD
   SET  TD.queue_rank = (SELECT  TD2.newrank
                                FROM  ( SELECT ticket_id,
                                            row_number() OVER (ORDER BY queue_rank, create_date) AS newrank
                                        FROM ticket_detail
                                        WHERE ticket_state = 'Queued'
                                        ) TD2
                                WHERE  TD.ticket_id = TD2.ticket_id
                            )
 WHERE  TD.ticket_state = 'Queued'
    OR  TD.queue_rank IS NOT NULL

字符串
我的查询似乎做了我需要它做的事情,并且在我迄今为止提出的所有测试用例中都有效。
这是最好的办法吗?
该代码是一个小的内部使用的应用程序。该表每年可能只有几百个条目,在任何时候队列中可能有30-40个条目。我计划仅在执行可能以某种方式影响队列顺序的操作之后运行重新排序查询。
嵌套的子查询让我很烦恼,而且查询正在为一个小查询进行两次完整扫描。对于我的用例来说,它仍然绰绰有余,希望能学到更好的方法来解决问题。

ljo96ir5

ljo96ir51#

您可以使用ROWID伪列进行关联,它实际上是指向一行的指针(而不是使用主键):

UPDATE  ticket_detail TD
SET  queue_rank = ( SELECT newrank
                    FROM   (
                      SELECT row_number() OVER (ORDER BY queue_rank, create_date) AS newrank
                      FROM   ticket_detail
                      WHERE  ticket_state = 'Queued'
                    ) TD2
                    WHERE  TD.ROWID = TD2.ROWID
                  )
WHERE  ticket_state = 'Queued'
OR     queue_rank IS NOT NULL

字符串
也可以使用MERGE语句:

MERGE INTO ticket_detail dst
USING (
  SELECT CASE ticket_state
         WHEN 'Queued'
         THEN ROW_NUMBER() OVER (
                PARTITION BY ticket_state
                ORDER BY queue_rank, create_date
              )
         ELSE NULL
         END AS newrank
  FROM   ticket_detail
  WHERE  ticket_state = 'Queued'
  OR     queue_rank IS NOT NULL
) src
ON (src.ROWID = dst.ROWID)
WHEN MATCHED THEN
  UPDATE
  SET queue_rank = newrank
  -- WHERE dst.queue_rank != src.new_rank
  -- OR    (dst.queue_rank IS NULL AND src.new_rank IS NOT NULL)
  -- OR    (dst.queue_rank IS NOT NULL AND src.new_rank IS NULL)


您可以选择向MERGE语句添加WHERE筛选器,以便仅在发生更改时更新行。

相关问题