2009-01-10 70 views
67

我在我的數據庫中的兩個表:PHP&MYSQL:如何解決JOIN操作中不明確的列名?

新聞( '身份證' - 新聞ID, '用戶' - 作者的用戶ID)

USERS( '身份證' - 用戶ID)

我想打一個SELECT * FROM news JOIN users ON news.user = user.id,現在當我在PHP的結果是這樣的:

$row = mysql_fetch_array($result),並獲得由$row['column-name']列名...我怎麼得到的消息ID和用戶ID,其相同的列名?

更新:謝謝大家的快速解答。別名似乎是最好的解決方案。

回答

109

您可以爲列別名,你是選擇:

$query = 'SELECT news.id AS newsId, user.id AS userId, [OTHER FIELDS HERE] FROM news JOIN users ON news.user = user.id' 
+1

這個答案作出了答案http://stackoverflow.com/questions/9233387/sql-should-i-use-a-join爲我工作,謝謝! – AVProgrammer 2012-02-10 22:24:42

+2

這種方法的主要缺點是與SELECT *不同,查詢與表結構緊密耦合。也就是說,無論何時在模式中添加/刪除/重命名列,都必須相應地更改查詢。 – 2014-06-12 16:11:06

+3

@RonInbar。 `SELECT *`是大系統中的維護噩夢。你建議添加一個列很簡單,如果使用`SELECT *`則不需要對SQL進行任何更改,但是在這裏指出的別名問題中情況並非如此。如果新領域很大,它也可能會帶來不必要的性能影響。它也可以打破期望一定數量或多個字段的客戶端控制。我可以繼續,但是當你瞭解它對可維護性和性能的影響時,`SELECT *`的好處就會很快消失。 – 2014-10-28 23:51:10

38

您可以使用數字索引($row[0])或更高,在MySQL使用AS

SELECT *, user.id AS user_id FROM ...

8

你可以做點像

SELECT news.id as news_id, user.id as user_id .... 

然後$row['news_id']將是新聞ID和$row['user_id']將用戶ID

1

如果你不覺得別名你也可以只是表名前綴。

這樣你可以更好地自動生成你的查詢。此外,這是一個最好的做法是不使用select *(這顯然不只是選擇的領域你需要 此外,只有明確命名你想擁有的字段慢。

SELECT 
    news.id, news.title, news.author, news.posted, 
    users.id, users.name, users.registered 
FROM 
    news 
LEFT JOIN 
    users 
ON 
    news.user = user.id 
19

我只是想通了這的。這可能是一個不好的做法,但在這種情況下,爲我工作。

我是懶惰的人誰不希望別名或帶有表前綴寫出每一列的名字之一。

你可以使用從特定表中選擇所有列在你的select語句中。

當你有重複的列名時,mysql會從第一個到最後一個覆蓋。來自第一個重複列名的數據將在它再次遇到該列名時被覆蓋。所以最後一次獲勝的重複列名稱。

如果我加入3個表,每個表都包含一個重複的列名,那麼select語句中表的順序將決定我爲重複列獲取的數據。

實施例:

SELECT table1.* , table2.* , table3.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup; 

在上面的例子中,dup我得到的值將是從table3

如果我想要dup成爲table1的值,該怎麼辦?

然後,我需要這樣做:

SELECT table3.* , table2.* , table1.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup; 

現在,table1在後面,所以dup值將會從表1的值。

我得到了我想要的價值dup,而不必寫出每一個怪異的列,我仍然得到所有的列工作。好極了!

我知道dup的值應該在所有3個表中都是相同的,但是如果table3沒有匹配值dup?然後dup在第一個例子中將是空白的,那將是一個無賴。

2

我對動態表有同樣的問題。 (假設有一個表可以加入一個id,但對其他字段沒有任何假設)。在這種情況下,你不會事先知道別名。

在這種情況下,你可以先拿到表的列名的所有動態表:

$tblFields = array_keys($zendDbInstance->describeTable($tableName)); 

其中$ zendDbInstance是Zend_Db的,或者您的實例可以使用的功能之一在這裏不依賴於Zend的php pdo: get the columns name of a table

然後所有動態表,你可以得到別名和使用$表名*對於那些你不需要的別名:

$aliases = ""; 
foreach($tblKeys as $field) 
    $aliases .= $tableName . '.' . $field . ' AS ' . $tableName . '_' . $field . ',' ; 
$aliases = trim(',', $aliases); 

ÿ你可以把這整個過程整合到一個通用函數中,只需要更簡潔的代碼或者如果你願意的話可以得到更多的懶惰:)

8

@Jason。你是正確的,除了PHP是罪魁禍首,而不是MySQL。如果你把你的JOIN放到Mysql Workbench中,你會得到三個名字完全相同的列(每個表有一個),但是沒有相同的數據(如果該表與JOIN沒有匹配,有些將會是null)。

在php中,如果您使用MYSQL_NUMmysql_fetch_array()那麼您將獲得所有列。問題是當您使用mysql_fetch_array()MYSQL_ASSOC時。然後,該函數內部,PHP正在建設的返回值,像這樣:

$row['dup'] = [value from table1] 

後來就......

$row['dup'] = [value from table2] 

...

$row['dup'] = [value from table3] 

那麼你只會得到來自table3的值。問題是來自mysql的結果集可以包含具有相同名稱的列,但php中的關聯數組不允許在數組中使用重複鍵。當數據保存在關聯數組中時,在php中,一些信息會悄悄丟失...

9

另一個提示:如果你想要有更乾淨的PHP代碼,你可以在數據庫中創建一個VIEW,

例如:

CREATE VIEW view_news AS 
SELECT 
    news.id news_id, 
    user.id user_id, 
    user.name user_name, 
    [ OTHER FIELDS ] 
FROM news, users 
WHERE news.user_id = user.id; 

在PHP:

$sql = "SELECT * FROM view_news"; 
-1

有兩種方法:

1. 使用別名;在這種方法中,您爲各個列提供新的唯一名稱(ALIAS),然後在PHP檢索中使用它們。

例如。

SQL $ SQL SELECT = student_id數據FEES_LINK,從students_fee_tbl LE​​FT student_class CLASS_LINK JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id

PHP $查詢= mysql_fetch_assoc($ SQL); //如果使用舊方法

$查詢= PDO->fetchAll(); //沒有確切的語法,但是這是目前的做法

foreach($query as $q){ 
echo $q['FEES_LINK']; 
} 

2.

使用放置位置或結果集列索引;在這裏,數組的位置被用來引用重複的列名。由於它們出現在不同的位置,所使用的索引號總是唯一的。 但是,索引定位編號從0開始。

例如。

$ SQL SELECT = student_id數據,從students_fee_tbl LE​​FT JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id

PHP

$查詢= mysql_fetch_assoc($ SQL)student_class; //如果使用舊方法

$查詢= PDO->使用fetchall(); //未確切的語法但是這是目前的做法

foreach($query as $q){ 

    echo $q[0]; 

} 

這兩件作品。

希望它有幫助。 :)