【问题标题】:Customized cyclic number design in database数据库中的自定义循环数设计
【发布时间】:2020-05-19 04:32:23
【问题描述】:

我需要一个数据库设计 (mysql 8.0+) 来支持从 1 到特定最大数的循环数系列,例如 1 到 3,然后将得到 1,2,3,1,2,3,... 作为查询结果分别和循环。我的版本已经成功运行,但希望寻求更好的本地版本。非常感谢。

我的脚本在这里,

CREATE TABLE IF NOT EXISTS `cyclic_series_number` (
  `category` VARCHAR(100) NOT NULL,
  `sn` int NOT NULL,
  `max` int NOT NULL,
  PRIMARY KEY (`category`)
);

然后,插入 2 条记录。第一条记录将是要测试的记录。

REPLACE INTO `cyclic_series_number` (`category`, `sn`, `max`) 
VALUES ('testing', 1, 3), ('ticket', 1, 999);

SELECT * FROM `cyclic_series_number`;
+--------------------------+
|   cyclic_series_number   |
+---+-----------+----+-----+
| # |  category | sn | max |
+---+-----------+----+-----+
| 1 | 'testing' | 1  |  3  |
+---+-----------+----+-----+
| 2 |  'ticket' | 1  | 999 |
+---+-----------+----+-----+

最后,提供一个存储过程。

想法是更新 (sn=sn+1) 并获取该数字以及必要的检查 sn+1 以查看是否超过最大数字。

以上所有逻辑同时运行。

DROP PROCEDURE IF EXISTS `get_new_sn`;
DELIMITER //
CREATE PROCEDURE get_new_sn(IN input_category varchar(100))
BEGIN
    SET @latest_sn = -1;
    UPDATE `cyclic_series_number`
    SET `sn` = (@latest_sn := case `sn` when `max` then 1 else `sn` + 1 end)
    WHERE `category` = @input_category;

    SELECT @latest_sn;
END //
DELIMITER ;

测试结果表明存储过程有效。

CALL get_new_sn('testing'); -- 2
CALL get_new_sn('testing'); -- 3
CALL get_new_sn('testing'); -- 1
CALL get_new_sn('testing'); -- 2
CALL get_new_sn('testing'); -- 3
CALL get_new_sn('testing'); -- 1
-- ...

参考文献

【问题讨论】:

  • 是mysql还是SQL Server(微软的产品)?如果是后者,则有一流的序列对象可以本地执行您想要的操作(通过循环)。如果这就是你的工作,我会写下来。
  • @BenThul mysql 拜托,非常感谢~
  • 我建议你简化问题;比如说,数字从 1 到 5。那就看meta.stackoverflow.com/questions/333952/…
  • @Strawberry 完全同意,所以实际上我已将其从 999,999 简化为 99。猜想已经很清楚了,不是吗?
  • 没有。见上文。

标签: mysql


【解决方案1】:
UPDATE sourcetable
SET sourcetable.num = subquery.num
FROM ( SELECT id, 1 + (ROW_NUMBER() OVER (ORDER BY id) - 1) % 99 num
       FROM sourcetable ) subquery
WHERE sourcetable.id = subquery.id;

99 是上限。

【讨论】:

  • 我很难想象这种情况会有用
  • @Akina 谢谢,但是你有 mysql 的版本吗?为什么从子查询更新?如果sourcetable不是小桌子,看起来必须小心。
  • @nwpie 您没有指定 MySQL 版本 - 所以我可能假设您使用的是最新版本。 为什么要从子查询更新? 这很简单——无论是在逻辑上还是在 SQL 文本中。您可以使用任何其他技术,没有问题。 如果 sourcetable 不是一个小表。我希望表中有主键(我的代码中为id)或至少有唯一索引?
  • @Akina 较早的帖子我不应该为mysqlsql-server 添加双重标签,现在已经删除了sql-server。对不起,这是我的错误。
  • 你用的是什么版本的mysql?此答案中的功能需要 8 或更高版本。
【解决方案2】:

保留您的存储过程...

更改开始的行: SET sn = (@latest_sn := case sn when ... .. ...

类似于: 设置sn = (sn + 1) % max;

模运算符在除法后返回余数...所以如果 sn+1 小于 max 则余数是 sn+1。一旦 sn+1 = 最大值,余数 = 0 并且它重新开始......这也意味着,最大值需要比最高允许值高 1......所以如果 sn 可以是 99 但不是 100,那么 max = 100。

【讨论】:

  • 谢谢,MOD 运营商更清楚了。虽然我们不允许 sn 为零,但您提到的这个公式将更改为 sn = (sn % max) + 1。因此保证不返回零。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-10
  • 1970-01-01
  • 2012-01-25
  • 1970-01-01
相关资源
最近更新 更多