PHP和MYSQL:如何解决JOIN操作中不明确的列名?
我在我的数据库中有两个表:
新闻('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,具有相同的列名?
更新:谢谢大家的快速答案。 别名似乎是最好的解决scheme。
您可以为要select的列设置别名:
$query = 'SELECT news.id AS newsId, user.id AS userId, [OTHER FIELDS HERE] FROM news JOIN users ON news.user = user.id'
您可以使用数字索引( $row[0]
)或更好,在MySQL中使用AS
:
SELECT *, user.id AS user_id FROM ...
我只是明白了这一点。 这可能是一个不好的做法,但在这种情况下对我很有帮助。
我是懒惰的人之一,不希望用表前缀别名或写出每个列名。
您可以通过在select语句中使用table_name.*
来select特定表中的所有列。
当你有重复的列名时,mysql会从头到尾进行覆盖。 当第一个重复列名的数据再次遇到该列名时将被覆盖。 所以上次获得的重复的列名称。
如果我join了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
值,而不必写出每一个吓人的列,我仍然得到所有的列工作。 好极了!
我知道dup
的值应该在所有3个表中都是相同的,但是如果table3
没有dup
的匹配值呢? 那么在第一个例子中dup
会是空白的,那将是一个无赖。
另一个提示:如果你想有更干净的PHP代码,你可以在数据库中创build一个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";
你可以做类似的事情
SELECT news.id as news_id, user.id as user_id ....
然后$row['news_id']
将是新闻ID, $row['user_id']
将是用户ID
@Jason。 你是正确的,除了PHP是罪魁祸首,而不是MySQL。 如果你把JOIN
放在Mysql Workbench中,你会得到三个名字完全相同的列(每个表有一个),但是没有相同的数据(如果这个表没有JOIN
匹配的话,一些将是null
的)。
在php中,如果您在mysql_fetch_array()
使用MYSQL_NUM
,那么您将获得所有列。 问题是当你使用mysql_fetch_array()
和MYSQL_ASSOC
。 然后,在这个函数里面,php正在创build如下的返回值:
$row['dup'] = [value from table1]
后来…
$row['dup'] = [value from table2]
…
$row['dup'] = [value from table3]
所以你只会得到table3的值。 问题是从MySQL的结果集可以包含具有相同名称的列,但在PHP中的关联数组不允许在数组中的重复键。 当数据保存在关联数组中时,在PHP中,一些信息将悄悄丢失…
我对dynamic表有同样的问题。 (假设有一个表可以join,但是没有任何其他字段的假设)。在这种情况下,你并不知道别名。
在这种情况下,您可以首先获取所有dynamic表的表列名称:
$tblFields = array_keys($zendDbInstance->describeTable($tableName));
其中$ zendDbInstance是Zend_Db的一个实例,或者你可以在这里使用其中的一个函数来不依赖Zend php pdo:获取表的列名
那么对于所有的dynamic表,你可以得到别名,并使用$ tableName。*为你不需要别名:
$aliases = ""; foreach($tblKeys as $field) $aliases .= $tableName . '.' . $field . ' AS ' . $tableName . '_' . $field . ',' ; $aliases = trim(',', $aliases);
你可以将整个过程包装成一个generics函数,只需要更干净的代码或者如果你愿意的话可以得到更多的懒惰:)
如果你不喜欢别名,你也可以在表名前加上。
这样你可以更好地自动生成你的查询。 另外,最好不要使用select *(这显然比只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
有两种方法:
1.使用别名; 在这个方法中,你给各个列赋予新的唯一名称(ALIAS),然后在PHP检索中使用它们。
例如。
SQL $ sql = SELECT student_id FEES_LINK,student_class CLASS_LINK from students_fee_tbl LEFT JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id
PHP $查询= mysql_fetch_assoc($ sql); / /如果使用旧的方法
$ query = PDO->fetchAll();
//不是确切的语法,但这是目前的方法
foreach($query as $q){ echo $q['FEES_LINK']; }
2。
使用地点位置或结果集列索引; 在这里,数组的位置被用来引用重复的列名。 由于它们出现在不同的位置,所使用的索引号总是唯一的。 但是,索引定位编号从0开始。
例如。
$ sql = SELECT students_fee_tbl中的student_id,student_class LEFT JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id
PHP
$ query = mysql_fetch_assoc($ sql); //如果使用旧的方法
$查询= PDO-> fetchAll(); / /不是确切的语法,但这是目前的做法
foreach($query as $q){ echo $q[0]; }
这两件作品。
希望它有帮助。 🙂