选择不在保留范围内的第一个可用号码

时间:2016-08-28 13:56:30

标签: mysql

我有两个表,boxescompanies。属于某个公司的每个方框都被添加到同一个商店(由字段store_id定义)并且在该商店中具有唯一编号,并且每个公司都可以保留框的范围(表公司中的字段boxes_from和boxes_to)。

CREATE TABLE IF NOT EXISTS `boxes` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `store_id` int(10) unsigned NOT NULL,
  `number` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=10 ;

INSERT INTO `boxes` (`id`, `store_id`, `number`) VALUES
(1, 1, 5),
(2, 1, 6),
(3, 1, 7),
(4, 1, 8),
(5, 1, 9),
(6, 1, 10),
(7, 1, 1),
(8, 1, 2),
(9, 1, 3);

+----+----------+--------+
| id | store_id | number |
+----+----------+--------+
|  1 |        1 |      5 |
|  2 |        1 |      6 |
|  3 |        1 |      7 |
|  4 |        1 |      8 |
|  5 |        1 |      9 |
|  6 |        1 |     10 |
|  7 |        1 |      1 |
|  8 |        1 |      2 |
|  9 |        1 |      3 |
+----+----------+--------+

CREATE TABLE IF NOT EXISTS `companies` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `boxes_from` int(10) unsigned NOT NULL,
  `boxes_to` int(10) unsigned NOT NULL,
  `store_id` smallint(5) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ;

INSERT INTO `companies` (`id`, `boxes_from`, `boxes_to`, `store_id`) VALUES
(1, 5, 10, 1),
(2, 0, 0, 1),
(3, 15, 20, 1);

+----+------------+----------+----------+
| id | boxes_from | boxes_to | store_id |
+----+------------+----------+----------+
|  1 |          5 |       10 |        1 |
|  2 |          0 |        0 |        1 |
|  3 |         15 |       20 |        1 |
+----+------------+----------+----------+

如果某个公司保留的范围内没有可用的号码,我需要找到新箱子的第一个可用号码。

例如,如果有两个保留范围,5-10和15-20,并且已有数字1-3的框,则第一个可用数字为4.如果有数字1-4的框,则下一个可用在第一个保留范围之后,数字是11。

我找到了一个解决方案,我找到了所有可能的下一个数字然后我必须将这个结果与表公司交叉加入以过滤掉保留范围。

SELECT number, COUNT(number) as cnt 
FROM (
    SELECT 1 as number FROM boxes WHERE NOT EXISTS (SELECT number FROM boxes WHERE store_id=1 AND number=1) 
    UNION 
    SELECT t1.number+1 as number FROM boxes t1 LEFT JOIN boxes t2 ON t2.number=t1.number+1 WHERE t1.store_id=1 AND t2.number IS NULL
    UNION 
    SELECT boxes_to+1 as number FROM companies WHERE store_id=1 AND boxes_from>0 AND boxes_to>0 AND boxes_to+1 NOT IN (
        SELECT number FROM boxes WHERE store_id=1)
    ) n, companies 
    WHERE number NOT BETWEEN boxes_from AND boxes_to GROUP BY number HAVING cnt=(SELECT COUNT(id) FROM companies
)

此查询返回所有可用的下一个数字:

+--------+-----+
| number | cnt |
+--------+-----+
|      4 |   3 |
|     11 |   3 |
|     21 |   3 |
+--------+-----+

有没有人有更好的解决方案?

0 个答案:

没有答案