ManyToMany关系修复

时间:2012-03-17 09:35:38

标签: mysql sql database split

我有以下遗留数据库设置:

CREATE TABLE `categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
)

CREATE TABLE `items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `category_ids` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
)

其中category_ids是由逗号分隔的类别ID的字符串:1, 10, 15, 6。有没有办法将此数据库转换为更常规的数据库(使用三个表,一个用于存储关系),仅使用SQL而不使用其他脚本?

1 个答案:

答案 0 :(得分:1)

MySQL没有CROSS APPLY或递归CTE,这是最简单的路线。

但是你只有这一次,所以你只需要快速入侵。

首先,找出类别列表中的最大项目数...

SELECT
  MAX(LEN(category_ids) - LEN(REPLACE(category_ids, ',', '')) + 1) AS max_items
FROM
  items

然后你可以这样做......

SELECT
  items.id,
  SUBSTRING_INDEX(
    SUBSTRING_INDEX(
      items.category_ids,
      ',',
      map.id  -- Get the first 'n' items from the list
    ),
    ',',
    -1        -- Get the last item from (the first 'n' items from the list)
  ) AS category_id
FROM
  items
INNER JOIN
(
            SELECT 1 as id
  UNION ALL SELECT 2 as id
  UNION ALL SELECT 3 as id
  etc, etc, up to the max number of items found previously
)
  AS map
    ON LEN(items.category_ids) - LEN(REPLACE(items.category_ids, ',', '')) + 1 >= map.id

我没有测试过,但我假设SUBSTRING_INDEX('last', ',', -1)返回'last'

我不是MySQL的专家,所以这可能不是最佳选择,但作为一次快速获胜,这种类型的结构应该有效...