将一个奇怪的 Mysql 查询更改为使用 group_concat 的 Postgresql

Posted

技术标签:

【中文标题】将一个奇怪的 Mysql 查询更改为使用 group_concat 的 Postgresql【英文标题】:Changing a weird Mysql query to Postgresql that uses group_concat 【发布时间】:2012-06-15 12:52:35 【问题描述】:

我正在将我们的后端数据库从 mysql 迁移到 postgres,并且正在迁移我们所有的旧查询/函数。他们中的大多数都是微不足道的,但今天我遇到了一个让我摸不着头脑的东西。这里是:

UPDATE
  k_coderound AS cr, k_coderound AS cr_m
SET
  cr.is_correct = IF(
    (SELECT GROUP_CONCAT(option_id ORDER BY variable_id) AS `values` FROM k_value    
         WHERE code_round_id=cr.id GROUP BY code_round_id) = 
    (SELECT GROUP_CONCAT(option_id ORDER BY variable_id) AS `values` FROM k_value 
         WHERE code_round_id=cr_m.id GROUP BY code_round_id),
    1,
    0
  )
WHERE     
 cr.is_master=0 
 AND cr_m.is_master=1 
 AND cr_m.object_id=cr.object_id 
 AND cr_m.content_type_id =cr.content_type_id       

我知道 Postgres 没有 group_concat,应该使用 array_agg。我的问题是我无法弄清楚到底发生了什么——这个查询是很久以前由一个不再和我们在一起的人写的。 Postgres 中缺少 IF 语句也使这一困难更加复杂。如果有人能够提供反馈或建议,我将不胜感激!

【问题讨论】:

您能否提供option_idvariable_idcode_round_id 列属于哪个表?他们属于k_value吗? option_id、variable_id、code_round_id属于k_value IF 通常在 PostgreSQL(以及任何其他符合标准的 SQL 数据库)中转换为 CASE 【参考方案1】:

很难说意图是什么。我的方法是首先找到一个返回“目标”数据的 SELECT 语句。

类似这样的:

select cr.is_correct,
       array_agg(case when kv1.code_round_id = cr.id then kv1.option_id else null end, ',' order by kv1.variable_id) as kv_values1,
       array_agg(case when kv2.code_round_id = cr_m.id then kv2.option_id else null end, ',' order by kv2.variable_id) as kv_values2
from k_coderound cr
  join k_value kv1 on kv1.code_round_id = cr.id
  join k_coderound cr_m 
       on cr_m.object_id=cr.object_id 
      and cr_m.content_type_id =cr.content_type_id 
  join k_value kv2 on kv2.code_round_id = cr_m.id
where cr.is_master=0 
  and cr_m.is_master=1 

这很可能是不正确的,但我认为它显示了非标准 MySQL 表达式如何转换为标准 SQL(从而转换为 PostgreSQL)

一旦这似乎做正确的事情,我会将其包装到 UPDATE 语句中:

update k_coderound cru
  set cr.is_correct = case 
                        when t.kv_values1 = t.kv_values2 then 1 
                        else 0 
                      end
from (select cr.ctid, 
             array_agg(case when kv1.code_round_id = cr.id then kv1.option_id else null end, ',' order by kv1.variable_id) as kv_values1,
             array_agg(case when kv2.code_round_id = cr_m.id then kv2.option_id else null end, ',' order by kv2.variable_id) as kv_values2
    from k_coderound cr
      join k_value kv1 on kv1.code_round_id = cr.id
      join k_coderound cr_m 
           on cr_m.object_id=cr.object_id 
          and cr_m.content_type_id =cr.content_type_id 
      join k_value kv2 on kv2.code_round_id = cr_m.id
    where cr.is_master=0 
      and cr_m.is_master=1 
) t
where t.ctid = cru.ctid

我很确定我错过了一些语法内容,但希望这能让你开始。

【讨论】:

以上是关于将一个奇怪的 Mysql 查询更改为使用 group_concat 的 Postgresql的主要内容,如果未能解决你的问题,请参考以下文章

mySQL查询将团队ID更改为团队名称并使其不为空

MYSQL执行sql语句,批量更改为指定时间段的随机时间

将 MySQL 命令行结果的输出格式更改为 CSV

Mysql将所有表名更改为小写[重复]

如何将 phpmyadmin 中的数据库类型从 mariadb 更改为 mysql?

将连接查询更改为 laravel