PHP& MYSQL:如何在JOIN操作中解决模糊列名?

时间:2009-01-10 17:34:25

标签: php sql mysql mysql-error-1052

我的数据库中有两个表:

NEWS('id' - 新闻ID,'用户' - 作者的用户ID)

USERS('id' - 用户ID)

我想制作一个SELECT * FROM news JOIN users ON news.user = user.id,现在当我在PHP中得到结果时,它就像:

$row = mysql_fetch_array($result),并按$row['column-name']获取列名...如何获取具有相同列名的新闻ID和用户ID?

更新:感谢大家的快速解答。别名似乎是最好的解决方案。

11 个答案:

答案 0 :(得分:113)

您可以为要选择的列设置别名:

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

答案 1 :(得分:40)

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

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

答案 2 :(得分:21)

我只想出了这个。这可能是一种不好的做法,但在这种情况下它对我有用。

我是一个懒惰的人,他们不想使用表前缀别名或写出每个列名。

您可以在select语句中使用table_name.*选择特定表格中的所有列。

如果您有重复的列名,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的值将是table1中的值。

我得到了dup我想要的价值,而不必写出每一个怪异的专栏,我仍然可以使用所有列。耶!

我知道所有3个表格中dup的值应该相同,但如果table3没有dup的匹配值,该怎么办?然后dup在第一个例子中将是空白的,那将是一个无赖。

答案 3 :(得分: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";

答案 4 :(得分:8)

您可以执行类似

的操作
SELECT news.id as news_id, user.id as user_id ....

然后$row['news_id']将成为新闻ID,$row['user_id']将成为用户ID

答案 5 :(得分:8)

@Jason。你是对的,除了php是罪魁祸首而不是mysql。如果你将JOIN放在Mysql Workbench中,你将得到三个具有完全相同名称的列(每个表一个)但不具有相同的数据(如果该表不匹配,则某些列将为null JOIN)。

如果您在MYSQL_NUM中使用mysql_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中,一些信息会无声地丢失......

答案 6 :(得分:2)

我对动态表有同样的问题。 (假设有一个id能够加入但没有任何其他字段的假设的表。)在这种情况下,你不知道手中的别名。

在这种情况下,您可以首先获取所有动态表的表列名称:

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

其中$ zendDbInstance是Zend_Db的一个实例,或者您可以使用此处的一个函数来不依赖Zend php pdo: get the columns name of a table

然后对于所有动态表,您可以获取别名并使用$ tableName。*来表示不需要别名的那些:

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

你可以将整个过程包装成一个通用函数,如果你愿意,可以使用更干净的代码或变得更加懒惰:)

答案 7 :(得分: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

答案 8 :(得分:0)

这是上面的答案,这很简单,并且可以处理返回的JSON结果。当您使用SELECT *时,SQL查询将自动为表名添加相同字段名的每个实例的前缀,而结果的JSON编码将发送回网页,忽略具有重复名的那些字段的值,而是返回NULL值

它的确切作用是包含重复字段名称的第一个实例,但其值设为NULL。字段名称的第二个实例(在另一个表中)被完全省略,包括字段名称和值。但是,当您直接在数据库上测试查询时(例如使用Navicat),所有字段都将返回到结果集中。只有当您接下来对该结果进行JSON编码时,它们才会具有NULL值,并且以后的重复名称将被完全省略。

因此,解决此问题的一种简便方法是先执行SELECT *,然后再为重复项添加别名字段。这是一个示例,其中两个表都具有相同名称的site_name字段。

SELECT *, w.site_name AS wo_site_name FROM ws_work_orders w JOIN ws_inspections i WHERE w.hma_num NOT IN(SELECT hma_number FROM ws_inspections) ORDER BY CAST(w.hma_num AS UNSIGNED);

现在,在已解码的JSON中,您可以使用字段wo_site_name,它具有一个值。在这种情况下,站点名称具有特殊字符,例如撇号和单引号,因此,在最初保存时进行编码,而在使用数据库结果时进行解码。

...decHTMLifEnc(decodeURIComponent( jsArrInspections[x]["wo_site_name"]))

您必须始终在SELECT语句中将*放在第一位,但是在它之后,您可以根据需要包含任意数量的命名和别名列,因为重复选择列不会造成问题。

答案 9 :(得分:-1)

有两种方法:

1。 使用别名;在此方法中,您将为各列提供新的唯一名称(ALIAS),然后在PHP检索中使用它们。

例如

<强> SQL $ sql = SELECT student_id来自students_fee_tbl的FEES_LINK,student_class CLASS_LINK LEFT JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id

<强> PHP $ query = mysql_fetch_assoc($ sql); //如果使用旧方法

$ query = PDO->fetchAll(); //不是确切的语法,但这是当前的方法

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

2

使用位置或结果集列索引;在此,数组位置用于引用重复的列名称。由于它们出现在不同的位置,因此将使用的索引号始终是唯一的。 但是,索引定位编号从0开始。

例如

$ sql = SELECT student_id,来自students_fee_tbl的student_class LEFT JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id

<强> PHP

$ query = mysql_fetch_assoc($ sql); //如果使用旧方法

$ query = PDO-&gt; fetchAll(); //不是确切的语法,但这是当前的方法

foreach($query as $q){

    echo $q[0];

}
这两件作品。

希望它有所帮助。 :)

答案 10 :(得分:-1)

在使用PDO进行数据库交互时,可以使用PDO::FETCH_NAMED获取模式来帮助解决该问题:

$sql = "SELECT * FROM news JOIN users ON news.user = user.id";
$data = $pdo->query($sql)->fetchAll(PDO::FETCH_NAMED);
foreach ($data as $row) {
    echo $row['column-name'][0]; // from the news table
    echo $row['column-name'][1]; // from the users table
    echo $row['other-column']; // any unique column name
}