我可以直接在 SQL 查询中处理返回值吗
Can I do a treatement of returning values directly in SQL query
我想知道是否可以使用 SQL 中的某些条目对 return 数据进行 SQL 查询。很抱歉,如果它不是明确的(这里不是英语,我想你已经明白了),那么让我们看一个例子:
$req = $bdd->prepare('SELECT u.u_id, u.u_name, um.um_id, um.um_name, um.um_value
FROM users as u
LEFT JOIN users_metas as um ON um.um_uid = u.u_id');
$prepare->execute();
$datas = $prepare->fetchAll();
所以在这里,我要在 $datas
中有一个像
这样的数组
$datas = array(
0 =>
u_id => 1
u_name => name
um_id => 1
um_name => meta_name1
um_value => meta_value1
1 =>
u_id => 1
u_name => name
um_id => 2
um_name => meta_name2
um_value => meta_value2
...
);
我想要的是:
$datas = array(
0 =>
u_id => 1
u_name => name
meta_name1 => meta_value1
meta_name2 => meta_value2
1 =>
u_id => an other user
...
);
在我手动处理 $datas
之后我已经有了这个,但我想知道我是否可以在没有治疗的情况下只用 SQL 来完成这个演示?
希望大家能理解我,有什么问题我会尽量说清楚。
问候。
MySQL解决方案
通过将 table 中的一列中的唯一值转换为输出中的多列,将 table 值表达式转换为 table 称为主元。与其他一些 DBMS 不同,MySQL 没有 PIVOT
或 CROSSTAB
函数,因此您不能针对此问题编写一个通用的解决方案。
如果您事先知道 um_name
的所有可能值,则可以使用聚合函数模拟此行为。
SELECT u.u_id, u.u_name,
MAX(CASE WHEN um_name = 'meta_name1' THEN um_value END) meta_name1,
MAX(CASE WHEN um_name = 'meta_name2' THEN um_value END) meta_name2
FROM users as u
LEFT JOIN users_metas as um ON um.um_uid = u.u_id
GROUP BY u.u_id, u.u_name;
此解决方案的缺点是您必须不断向查询添加 MAX(CASE WHEN um_name = '...' THEN um_value END)
列以获取 um_name
的每个可能值。
理论上,您可以通过首先选择所有不同的 um_name
值在 PHP 中生成此查询,但这不会使您的代码更简单或更快,因此没有太多意义。
PHP解决方案
作为替代方案,只需几行 PHP 即可将您当前的输出从 fetchAll()
转换为您想要的格式。
$out = [];
array_walk($datas, function($v) use(&$out) {
$out[$v["u_id"]] = (isset($out[$v["u_id"]]) ? $out[$v["u_id"]] : [])
+ ["u_id" => $v["u_id"],
"u_name" => $v["u_name"],
$v["um_name"] => $v["um_value"]];
});
$out = array_values($out);
如果 users_metas
table 中不存在记录,则不会设置键,因此您需要在访问特定值之前使用 isset
进行检查如果不是对所有用户都存在。
我想知道是否可以使用 SQL 中的某些条目对 return 数据进行 SQL 查询。很抱歉,如果它不是明确的(这里不是英语,我想你已经明白了),那么让我们看一个例子:
$req = $bdd->prepare('SELECT u.u_id, u.u_name, um.um_id, um.um_name, um.um_value
FROM users as u
LEFT JOIN users_metas as um ON um.um_uid = u.u_id');
$prepare->execute();
$datas = $prepare->fetchAll();
所以在这里,我要在 $datas
中有一个像
$datas = array(
0 =>
u_id => 1
u_name => name
um_id => 1
um_name => meta_name1
um_value => meta_value1
1 =>
u_id => 1
u_name => name
um_id => 2
um_name => meta_name2
um_value => meta_value2
...
);
我想要的是:
$datas = array(
0 =>
u_id => 1
u_name => name
meta_name1 => meta_value1
meta_name2 => meta_value2
1 =>
u_id => an other user
...
);
在我手动处理 $datas
之后我已经有了这个,但我想知道我是否可以在没有治疗的情况下只用 SQL 来完成这个演示?
希望大家能理解我,有什么问题我会尽量说清楚。
问候。
MySQL解决方案
通过将 table 中的一列中的唯一值转换为输出中的多列,将 table 值表达式转换为 table 称为主元。与其他一些 DBMS 不同,MySQL 没有 PIVOT
或 CROSSTAB
函数,因此您不能针对此问题编写一个通用的解决方案。
如果您事先知道 um_name
的所有可能值,则可以使用聚合函数模拟此行为。
SELECT u.u_id, u.u_name,
MAX(CASE WHEN um_name = 'meta_name1' THEN um_value END) meta_name1,
MAX(CASE WHEN um_name = 'meta_name2' THEN um_value END) meta_name2
FROM users as u
LEFT JOIN users_metas as um ON um.um_uid = u.u_id
GROUP BY u.u_id, u.u_name;
此解决方案的缺点是您必须不断向查询添加 MAX(CASE WHEN um_name = '...' THEN um_value END)
列以获取 um_name
的每个可能值。
理论上,您可以通过首先选择所有不同的 um_name
值在 PHP 中生成此查询,但这不会使您的代码更简单或更快,因此没有太多意义。
PHP解决方案
作为替代方案,只需几行 PHP 即可将您当前的输出从 fetchAll()
转换为您想要的格式。
$out = [];
array_walk($datas, function($v) use(&$out) {
$out[$v["u_id"]] = (isset($out[$v["u_id"]]) ? $out[$v["u_id"]] : [])
+ ["u_id" => $v["u_id"],
"u_name" => $v["u_name"],
$v["um_name"] => $v["um_value"]];
});
$out = array_values($out);
如果 users_metas
table 中不存在记录,则不会设置键,因此您需要在访问特定值之前使用 isset
进行检查如果不是对所有用户都存在。