Php 不使用GROUP_CONCAT的原因?
我刚刚发现了这个非常有用的MySQL函数Php 不使用GROUP_CONCAT的原因?,php,mysql,sql,Php,Mysql,Sql,我刚刚发现了这个非常有用的MySQL函数GROUP\u CONCAT。它对我来说是如此的有用和过于简化,以至于我真的害怕使用它。主要是因为自从我开始从事网络编程已经有一段时间了,我在任何地方都没有见过它。下面是一个很棒的用法示例 表clients为每个客户机保存一行具有唯一ID的客户机(您不会说…。 表货币有3列客户id、货币和金额 现在,如果我想从clients表中获取用户15的名称及其余额,使用“旧”数组覆盖方法,我必须使用以下SQL SELECT id, name, currency, a
GROUP\u CONCAT
。它对我来说是如此的有用和过于简化,以至于我真的害怕使用它。主要是因为自从我开始从事网络编程已经有一段时间了,我在任何地方都没有见过它。下面是一个很棒的用法示例
表clients
为每个客户机保存一行具有唯一ID的客户机(您不会说…。表
货币
有3列客户id
、货币
和金额
现在,如果我想从clients
表中获取用户15的名称
及其余额,使用“旧”数组覆盖方法,我必须使用以下SQL
SELECT id, name, currency, amount
FROM clients LEFT JOIN currencies ON clients.id = client_id
WHERE clients.id = 15
然后在php中,我必须循环遍历结果集并执行数组覆盖(我真的不太喜欢这样做,尤其是在大量结果集中)
但是,对于新发现的函数,我可以使用
SELECT id, name, GROUP_CONCAT(currency) as currencies GROUP_CONCAT(amount) as amounts
FROM clients LEFT JOIN currencies ON clients.id = client_id
WHERE clients.id = 15
GROUP BY clients.id
然后在应用程序级别上,事情是如此的棒和漂亮
$results = $stmt->fetchAll();
foreach($results as $k => $v){
$results[$k]['currencies'] = array_combine(explode(',', $v['currencies']), explode(',', $v['amounts']));
}
我想问的问题是,在性能或任何方面使用此函数是否有任何缺点,因为对我来说,它看起来就像纯粹的令人敬畏的东西,这让我认为人们不经常使用它一定是有原因的
编辑:
我想问,最终,除了数组覆盖之外,还有什么其他选项可以从MySQL结果集中得到一个多维数组,因为如果我选择15列,那么编写beast真的是一件非常痛苦的事。我看到的
GROUP_CONCAT
最大的问题是它对MySql非常特定:如果你想移植你的代码以在任何其他平台上运行,你必须重写所有使用GROUP_CONCAT
的查询。例如,您的第一个查询的可移植性要高得多—您可能可以针对任何主要的RDBMS引擎运行它,而无需更改其中的单个字符
如果您只使用MySql(比如,因为您正在编写一个专门针对MySql的工具),使用GROUP\u CONCAT
的查询可能会更快,因为RDBMS会为您做更多的工作,节省数据传输的大小。- 使用GROUP_CONCAT()通常通过逻辑调用GROUP并创建临时表,这通常会对性能造成很大的负面影响。有时,您可以添加正确的索引以避免GROUPBY查询中的temp表,但并非在所有情况下都如此
- 正如@MarcB指出的,组连接字符串的默认长度限制非常短,许多人对截断列表感到困惑。你可以增加限额
- 在PHP中将字符串分解为数组并不是免费的。仅仅因为在PHP中可以在一个函数调用中完成,并不意味着它是性能最好的。我还没有对差异进行基准测试,但我怀疑你也没有
- GROUP_CONCAT()是一个MySQLism。其他SQL产品并不广泛支持它。在某些情况下(例如SQLite),它们有一个GROUP_CONCAT()函数,但它的工作原理与MySQL中的不完全相同,因此如果您必须支持多个RDBMS后端,这可能会导致混淆错误。当然,如果您不需要担心移植,这不是一个问题
- 如果要从
表中获取多个列,则需要多个GROUP_CONCAT()表达式。是否保证列表的顺序相同?也就是说,一个列表中的第三个字段是否对应于下一个列表中的第三个字段?答案是否定的——除非在GROUP_CONCAT()中使用currences
子句指定订单order BY
我不是想说groupconcat()不好!它在很多情况下都非常有用。但是,试图制定任何一刀切的规则来使用(或避免)任何函数或语言功能都是过于简单的。这很方便,但并不普遍方便。它可以返回的字符串的长度是有限的,默认情况下通常是1024个字符。如果你有一个“大”数据集,你的压缩字符串很容易超过1024个字符,它将被自动截断/损坏。这里已经介绍了长度可以配置端口我的代码?伙计,如果我的房间温度发生变化,我的代码就不起作用了!lol
:D
我在这个答案中错过的是一个解释,为什么从来没有一个好的理由在第一时间甚至需要group_concat。@popovitsj数组覆盖大量的结果集和选定的列是低效的,对代码来说是痛苦的,这不是一个好的理由吗?(不是说group_concat更有效,只是在想)@popovitsj,请看我的答案,包括评论中的讨论。@php_nub_qq,我会根据具体情况进行测试。正如您所说,在任一表中获取的行数都会影响哪个解决方案更有效。别猜,测试@我不明白为什么你认为你需要这个数组覆盖,但当然,我不知道你的应用程序的其他任何东西。我喜欢相信,你不经常看到group_concat()的原因是因为它违背了关系数据库的一个核心原则,我认为对这个函数的需求主要是由那些没有真正“获取”关系数据库的人推动的。
$results = $stmt->fetchAll();
foreach($results as $k => $v){
$results[$k]['currencies'] = array_combine(explode(',', $v['currencies']), explode(',', $v['amounts']));
}