2011-02-17 108 views
0

免責聲明:我首先在另一個網站上發佈了這個MySQL表連接,嵌套選擇語句或創建視圖?

我有一張約200列寬的表(res_table)。其中一列被命名爲「feature_lk」,它由一串數字組成,它們是「|」分隔。數字代表位於另一個名爲「功能」的表中的功能類別

感謝此線程:http://www.kirupa.com/forum/showthread.php?t=224203我想出瞭如何解析功能!

現在我的問題是怎麼看他們呢?我覺得我要麼加入我的兩個表,但我不知道如何,或者我需要爲我解析的每個功能執行另一個選擇查詢。這就是我必須解決的問題(刪除連接字符串張貼目的)

PHP Code: 
<?php 
$sql = ("SELECT * FROM res_table"); 
$result = mysql_query($sql); 

while($row = mysql_fetch_array($result)) 
{ 
    $feature_string = $row['features_lk']; 
    $features = explode('|', $feature_string); 

    foreach($features as $feature) { 
     $feature = trim($feature); 
     echo $feature.': '; 

     $sql2 = "SELECT * from features where features.feature_id like $feature"; 
     $result2 = mysql_query($sql2); 
     while ($row2 = mysql_fetch_array($result2)) 
     { 
      $feat_desc = $row2['feature_description']; //this is another column in the features table 
      echo $feat_desc . '<br>'; 
     } 
    } 
    echo '<br>'; 
} 
?> 

如此,因爲當我運行它,我會得到有關結果看起來像這樣的作品OK:

13: None 
62: Water Softener - Rented 
71: Full 
168: Barn 
222: Storage Shed 
226: Walkout 
309: Detached 
347: 2 Story 
384: Attic Storage 
439: Laundry Hook Up 
466: Rural 
476: Trees 
512: School Bus 
562: Mud Room 
563: Pantry 
2273: Septic Tank 
643: Private Well 

我的問題是:有沒有更好的辦法做到這個?主res_table中有大約10k行,只有幾百個點擊,您可以看到,所執行的選擇語句的數量在任何時候都很快就會變大。

我敢肯定,這是PHP + MySQL的101的東西,但我只是一個初學者所以任何想法?提前致謝。

回答

2

當你存儲在列多於一條信息,你的表是不歸。對feature_lk進行查找必然會很慢並且很困難。feature_lk應該成爲它自己的表:

表feature_lk:

  • res_table_id FK到res_table
  • FEATURE_ID FK到功能表
  • 主鍵(res_table_id,FEATURE_ID)

然後你查詢是:

SELECT f.* from features f 
    JOIN feature_lk lk ON (f.id=lk.feature_id) 
    JOIN res_table r ON (lk.res_table_id=r.id); 

僅限一個查詢。沒有循環。不解析功能。

ETA

用於通過具有任意性質

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `dorepeat` $$ 
CREATE PROCEDURE `dorepeat`(in ToBeSplit LONGTEXT , in Splitter CHAR) 
Begin 

DECLARE TotalLength INT; 
DECLARE SplitterPosition INT; 
DECLARE SubstringLength INT; 
DECLARE SubstringStart INT; 

DROP Table if exists Split_Values; 
CREATE temporary TABLE Split_Values (split varchar(255)); 

SET TotalLength = LENGTH(ToBeSplit); 
SET SplitterPosition = LOCATE(Splitter, ToBeSplit); 
SET SubstringStart = 1; 

ss: WHILE SplitterPosition < TotalLength DO 
     IF SplitterPosition!=0 THEN 
       SET SubstringLength = SplitterPosition - SubstringStart; 
       Insert into Split_Values VALUES (SUBSTRING(ToBeSplit,SubstringStart,SubstringLength)); 
       SET SubstringStart = SplitterPosition+1; 
       SET SplitterPosition = LOCATE(Splitter, ToBeSplit, SplitterPosition+1); 
     ELSE 
       Insert into Split_Values VALUES (SUBSTRING(ToBeSplit,SubstringStart)); 
       SET SplitterPosition=TotalLength; 
     END IF; 
END WHILE ss; 
End $$ 

DELIMITER ; 

在另一過程使用dorepeat分裂的任意長度的字符串存儲過程使得臨時表與res_table_id和每個特徵:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `multido` $$ 
CREATE PROCEDURE `multido`() 
Begin 
DECLARE done INT default 0; 
DECLARE rt_id INT (10); 
DECLARE features LONGTEXT; 
DECLARE mycur cursor for select distinct res_table_id, feature_lk from res_table WHERE feature_lk!=''; 
DECLARE continue handler for sqlstate '02000' set done=1; 
drop table if exists tmpfeatures; 
create temporary table tmpfeatures(res_table_id int(10), feature varchar(255)); 
open mycur; 
repeat 
    fetch mycur into rt_id,features; 
    call dorepeat(features,'|'); 
    insert into tmpfeatures select rt_id, trim(split) from Split_Values; 
until done end repeat; 
close mycur; 

End $$ 

DELIMITER ; 
+0

現在,我既控制了模式,也控制了模式。它的MLS通過文本文件共享數據。我正在採取這些文本文件(選項卡分離)並將其導入到一個MySQL數據庫表。我想我可以在導入時解析出這些功能並創建一個新表格?這甚至有可能嗎? – Edward 2011-02-18 05:13:57

0

你感覺這裏窮數據庫建模的痛苦。如果您對數據庫架構有任何控制權,那麼您應該修正它,以便將其正確化。每當你在數據庫中看到一個管道(或者逗號,或者製表符或者其他)的列表時,你應該對它非常懷疑。

你應該在你的表和類別之間有一個連接表,通常命名爲類似RES_CATEGORIES的連接表,其中包含來自RES的ID和來自CATEGORIES的ID。這是模型化關係數據庫中多對多關係的標準方法。

如果你無法控制的模式,不是你最好的選擇是隻解析出代碼並執行一個單獨的查詢(或查詢)來獲取類信息。您至少可以在where子句中指定多個類別ID,使其稍微不痛。

0

從我在你的問題理解,你需要一箇中間表。例如,您有表tbl_user和tbl_features,用戶可以訂閱許多功能,並且每個功能都可以由多個用戶訂閱。

您的數據庫可以通過額外的表tbl_userfeatures {userFeatureID,userID,featureID}更易於管理,該表可鏈接另外兩個表並允許您添加不同的組合。

0

一個簡單的優化步驟將是在一個步驟中獲取特徵,而不是循環它們。事情是這樣的:

$result = mysql_query('SELECT * FROM res_table'); 
while ($row = mysql_fetch_array($result)) { 
    $features = str_replace('|', ',', $features); 
    $result2 = mysql_query("SELECT * FROM features WHERE feature_id IN $features"); 
    while ($row2 = mysql_fetch_array($result2) { 
     printf('%d: %s', $row2['feature_id'], $row2['feature_description']); 
    } 
} 

這對每行中res_table一個查詢,而不是一個對每個功能。

但是在你這樣做之前,先聽其他的迴應。如果您能夠將數據庫模式更改爲更好的模式,請這樣做!