2011-03-11 98 views
1

我在表格中以varchar(255)的形式存儲數字列表,並且希望在另一個查詢的「IN()子句中使用此列表」我需要一些幫助讓MySql使用子查詢輸出一些結果

這裏是我的意思是:

表數據:

CREATE TABLE IF NOT EXISTS `session_data` (
    `visible_portf_ids` varchar(255) DEFAULT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

INSERT INTO `session_data` (`visible_portf_ids`) VALUES 
('45,44,658,659,661,45,44,658,659,661') 

我想運行這樣的查詢返回的投資組合的 「QUERY#1」 的名單:

SELECT portfolio_hierarchy_id, account_id, name, leaf_node_portf_id 
FROM portfolio_hierarchy 
WHERE account_id = 1 
AND leaf_node_portf_id IN 
      (
       (SELECT visible_portf_ids 
       FROM session_data 
       WHERE username = 'ronedog') 
      ) 
ORDER BY name ASC 

以上查詢的結果只返回1行,當總共有3行應該返回時。

如果我單獨運行子查詢是這樣的:

(SELECT visible_portf_ids 
FROM session_data 
WHERE username = 'ronedog') 

它會返回像這樣的列表:

45,44,658,659,661,45,44,658,659,661 

但是,當我運行上面的查詢#1,數據只有一行,它與「45」的「visible_portf_ids」相關聯被返回。

如果我更換這樣的硬編碼值的子查詢:

SELECT portfolio_hierarchy_id, account_id, name, leaf_node_portf_id 
FROM portfolio_hierarchy 
WHERE account_id = 1 
AND leaf_node_portf_id IN (45,44,658,659,661,45,44,658,659,661) 
ORDER BY name ASC 

然後我得到的所有3行我很期待。

我猜MySql返回列表作爲一個字符串,因爲它存儲爲一個varchar(),所以它停止處理後發現第一個「visible_portf_ids」,這是「45」,但我不是非常肯定。

任何人有任何想法,我可以解決這個問題?

在此先感謝。

+0

能否通過刪除嘗試'()'從子查詢 – 2011-03-11 05:37:30

回答

2

您應該考慮重構將表中存儲每個值的表格,而不是將它們連接在一起。

在那之前,你可以使用FIND_IN_SET()功能:

AND FIND_IN_SET(leaf_node_portf_id, 
       (SELECT visible_portf_ids 
       FROM session_data 
       WHERE username = 'ronedog' 
       LIMIT 1) 
      ) > 0 
+0

+1,打我給它X-) – 2011-03-11 05:41:12

+0

這個偉大的工程。但是,爲什麼使用它會成爲問題呢?爲什麼最好創建一個單獨的表併爲每個ID插入一個新行......這個表可能會變得相當大。只是想知道你的解決方案的問題是什麼,以及爲什麼新桌子更好。 Thaks爲你提供幫助。 – Ronedog 2011-03-11 06:12:48

+0

這違反了[數據庫規範化](http://en.wikipedia.org/wiki/Database_normalization)當您有兩個線程同時更新值時會發生什麼?獎勵是通過比較數字獲得的表現(每行列是單個數字)如果您擔心表增長,您可以隨時添加索引。 – 2011-03-11 06:29:57

0

不幸的是MySQL沒有一個功能來分割分隔字符串。您的IN參數是一個包含子查詢結果的單個字符串。當你對它進行硬編碼時,它的工作原理是MySQL解析值。

我建議您重新設計您的數據庫,將可見端口列表作爲單獨的行存儲在單獨的表中。然後你可以檢索它們並像你嘗試的那樣在子查詢中使用它們。