我的数据库中有两个表:
带有列的 NEWS 表:
id
- 新闻 IDuser
- 作者的用户ID)
带有列的 USERS 表:
id
- 用户 ID
我想执行这个 SQL:
SELECT * FROM news JOIN users ON news.user = user.id
当我在 PHP 中获得结果时,我想获得关联数组并通过$row['column-name']
. 如何获得具有相同列名的新闻 ID 和用户 ID?
我的数据库中有两个表:
带有列的 NEWS 表:
id
- 新闻 IDuser
- 作者的用户ID)带有列的 USERS 表:
id
- 用户 ID我想执行这个 SQL:
SELECT * FROM news JOIN users ON news.user = user.id
当我在 PHP 中获得结果时,我想获得关联数组并通过$row['column-name']
. 如何获得具有相同列名的新闻 ID 和用户 ID?
您可以为您选择的列设置别名:
$query = 'SELECT news.id AS newsId, user.id AS userId, [OTHER FIELDS HERE] FROM news JOIN users ON news.user = user.id'
您可以使用数字索引 ( $row[0]
) 或更好,AS
在 MySQL 中使用:
SELECT *, user.id AS user_id FROM ...
我只是想通了。这可能是一个不好的做法,但在这种情况下它对我有用。
我是不想为每个列名加上表前缀的别名或写出的懒人之一。
table_name.*
您可以通过在 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
在第一个示例中将是空白的,这将是一个无赖。
@杰森。你是对的,除了 php 是罪魁祸首而不是 mysql。如果你把你JOIN
放在 Mysql Workbench 中,你会得到三个名称完全相同的列(每个表一个),但数据不同(null
如果该表与JOIN
.
如果你在 php 中使用MYSQL_NUM
,mysql_fetch_array()
那么你将获得所有列。问题是当您使用mysql_fetch_array()
with时MYSQL_ASSOC
。然后,在该函数内部,php 正在构建返回值,如下所示:
$row['dup'] = [value from table1]
后来……
$row['dup'] = [value from table2]
...
$row['dup'] = [value from table3]
所以你只会从 table3 中得到值。问题是来自 mysql 的结果集可以包含具有相同名称的列,但 php 中的关联数组不允许数组中的重复键。当数据保存在关联数组中时,在php中,一些信息会默默地丢失......
另一个提示:如果你想有更干净的 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";
你可以做类似的事情
SELECT news.id as news_id, user.id as user_id ....
然后$row['news_id']
将是新闻 id 和$row['user_id']
用户 id
我对动态表也有同样的问题。(假设有一个 id 可以加入但对其余字段没有任何假设的表。)在这种情况下,您事先不知道别名。
在这种情况下,您可以首先获取所有动态表的表列名称:
$tblFields = array_keys($zendDbInstance->describeTable($tableName));
其中 $zendDbInstance 是 Zend_Db 的一个实例,或者您可以使用此处的一个函数来不依赖 Zend php pdo:获取表的列名
然后对于所有动态表,您可以获得别名并将 $tableName.* 用于不需要别名的那些:
$aliases = "";
foreach($tblKeys as $field)
$aliases .= $tableName . '.' . $field . ' AS ' . $tableName . '_' . $field . ',' ;
$aliases = trim($aliases, ',');
您可以将整个过程包装到一个通用函数中,并且只需要更简洁的代码或根据需要变得更懒惰:)
当使用 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
}
如果您不想使用别名,您也可以只为表名添加前缀。
这样,您可以更好地自动生成查询。此外,最好不要使用 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
这是上面的答案,它既简单又适用于返回的 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 语句的前面,但在它之后您可以包含任意数量的命名和别名列,因为重复选择一个列不会产生任何问题。
有两种方法:
使用别名;在此方法中,您为各个列赋予新的唯一名称 (ALIAS),然后在 PHP 检索中使用它们。例如
SELECT student_id AS FEES_LINK, student_class AS CLASS_LINK
FROM students_fee_tbl
LEFT JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id
然后在 PHP 中获取结果:
$query = $PDO_stmt->fetchAll();
foreach($query as $q) {
echo $q['FEES_LINK'];
}
使用位置或结果集列索引;在此,数组位置用于引用重复的列名。由于它们出现在不同的位置,因此将使用的索引号始终是唯一的。但是,索引定位编号从 0 开始。例如
SELECT student_id, student_class
FROM students_fee_tbl
LEFT JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id
然后在 PHP 中获取结果:
$query = $PDO_stmt->fetchAll();
foreach($query as $q) {
echo $q[0];
}