2012-03-17 84 views
3

我有以下遺留數據庫設置:多對多關係固定

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

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的專家,所以這可能不是最優的,但作爲一個時間迅速贏得thistype結構應該工作...

+0

我希望有一種方法來生成映射表獨立的最大數。現在它似乎工作,雖然不是最佳的,但只要它有效,誰在乎? :) – Shark 2012-03-17 14:45:14

+0

順便說一下,我們可以使用'UNION'而不是'UNION ALL',而MySQL目前沒有'LEN'功能,那裏是'LENGTH'。 – Shark 2012-03-17 14:47:11

+1

@Shark - Union會增加重複數據刪除的開銷。 Union All沒有。如果您不關心或需要重複數據刪除,那麼建議使用Union All。 – MatBailie 2012-03-17 23:52:15