GROUP_CONCAT具有多个列的分组依据

如何解决GROUP_CONCAT具有多个列的分组依据

我在选择GROUP_CONCAT时遇到了问题,该行也应该包含与该问题类似的行号GROUP_CONCAT numbering 区别在于我必须按多列分组。

例如,我有2个表reviewreview_detail
模式(MySQL v5.5)

create table review (
  `id` int(11) NOT NULL AUTO_INCREMENT,`submission_id` int(11) NOT NULL,PRIMARY KEY (`id`)
);

create table review_detail (
  `id` int(11) NOT NULL AUTO_INCREMENT,`review_id` int(11),`category_id` int(11),`rating` varchar(100),PRIMARY KEY (`id`)
);

insert into review (`id`,`submission_id`) values (1,1),(2,(3,2),(4,3),(5,(6,(7,(8,3);

insert into review_detail (`review_id`,`category_id`,`rating`)
values 
(1,1,' submission 1.1 cat 1'),(1,2,' submission 1.1 cat 2'),' submission 1.2 cat 1'),' submission 1.2 cat 2'),' submission 2.1 cat 1'),' submission 2.1 cat 2'),' submission 3.1 cat 1'),' submission 1.3 cat 1'),' submission 1.3 cat 2'),' submission 3.2 cat 1'),' submission 3.2 cat 2'),' submission 2.2 cat 1'),' submission 2.2 cat 2'),' submission 3.3 cat 1'),' submission 3.3 cat 2')
;

查询#1

SELECT * FROM review;

| id  | submission_id |
| --- | ------------- |
| 1   | 1             |
| 2   | 1             |
| 3   | 2             |
| 4   | 3             |
| 5   | 1             |
| 6   | 3             |
| 7   | 2             |
| 8   | 3             |

查询#2

SELECT * FROM review_detail;

| id  | review_id | category_id | rating                |
| --- | --------- | ----------- | --------------------- |
| 1   | 1         | 1           |  submission 1.1 cat 1 |
| 2   | 1         | 2           |  submission 1.1 cat 2 |
| 3   | 2         | 1           |  submission 1.2 cat 1 |
| 4   | 2         | 2           |  submission 1.2 cat 2 |
| 5   | 3         | 1           |  submission 2.1 cat 1 |
| 6   | 3         | 2           |  submission 2.1 cat 2 |
| 7   | 4         | 1           |  submission 3.1 cat 1 |
| 8   | 4         | 2           |  submission 3.1 cat 1 |
| 9   | 5         | 1           |  submission 1.3 cat 1 |
| 10  | 5         | 2           |  submission 1.3 cat 2 |
| 11  | 6         | 1           |  submission 3.2 cat 1 |
| 12  | 6         | 2           |  submission 3.2 cat 2 |
| 13  | 7         | 1           |  submission 2.2 cat 1 |
| 14  | 7         | 2           |  submission 2.2 cat 2 |
| 15  | 8         | 1           |  submission 3.3 cat 1 |
| 16  | 6         | 2           |  submission 3.3 cat 2 |

每个提交的评论(外键= submission_id)都有多个带有category_id的review_detail条目(在我的示例中,只有2个类别(1,2)与查询无关)。 / p>

我必须创建一个选择,使我得到按submission_idcategory_id分组的GROUP_CONCAT。

Concat字符串应返回
Reviewer 1: {rating},Reviewer 2: {rating},Reviewer 3: {rating} etc.

例如对于submitt_id = 1和category_id = 1,组concat应该返回
Reviewer 1: submission 1.1 cat 1,Reviewer 2: submission 1.2 cat 1,Reviewer 3: submission 1.3 cat 1

但是我无法正确设置concat组中的编号。

到目前为止,我已经进行了多次测试。

只有一个列计数器的组(有效)
https://www.db-fiddle.com/f/6hA4Vft1mQGdw2Pew2An2T/3
Reviewer 1: submission 1.1 cat 1 of review 1 / Reviewer 2: submission 3.3 cat 1 of review 8 / Reviewer 3: submission 2.2 cat 1 of review 7 / Reviewer 4: submission 3.2 cat 1 of review 6 / ... etc.

SELECT
    --review.submission_id,review_detail.category_id,@i,GROUP_CONCAT(
        CONCAT(
            'Reviewer ',@i := @i + 1,': ',rating,' of review ',review_id
        )
    SEPARATOR ' / '
    ) concatText,@i := 0
FROM
    review_detail
LEFT JOIN review ON review.id = review_detail.review_id,(
SELECT
    @i := 0
) init
GROUP BY
    review_detail.category_id
ORDER BY
    review_detail.category_id ASC
;

使用if和比较2个分组列的字符串进行测试(不起作用)
https://www.db-fiddle.com/f/3woAVSw5hrav15jAmuWVdT/3
Reviewer 1: submission 1.1 cat 1 of review 1 / Reviewer 1: submission 1.2 cat 1 of review 2 / Reviewer 1: submission 1.3 cat 1 of review 5

SELECT
    submission_id,category_id,@grp,CONCAT_WS("-",submission_id,category_id) AS catgroup,@i := IF(
                @grp = CONCAT_WS("-",category_id),@i + 1,IF(
                    @grp := CONCAT_WS("-",1
                )
            ),review_id
        )
    ORDER BY review_id,category_id 
    SEPARATOR ' / '
    ) concatText
FROM
    review_detail
LEFT JOIN review ON review.id = review_detail.review_id,(
SELECT
    @i := 0,@grp := ''
) init
GROUP BY
    review.submission_id,review_detail.category_id

那么有人对多列进行分组时,有谁知道正确地在GROUP_CONCAT调用中编号的方法吗?

解决方法

您应避免在生产代码中使用用户定义的变量。

manual for MySQL 5.6中说:

作为一般规则,除了在SET语句中,永远不要 为用户变量分配一个值,并在同一变量中读取该值 声明。

甚至在documentation for 8.0中也声明:

涉及用户变量的表达式的求值顺序为 未定义。例如,不能保证SELECT @a,@a:=@a+1 首先评估@a,然后执行分配。

在将来的版本中,这可能完全不再起作用:

以前的MySQL版本可以为一个值分配一个值 SET以外的语句中的用户变量。此功能是 MySQL 8.0支持向后兼容,但受制于 在将来的MySQL版本中删除。

所以这是一个没有用户定义变量的解决方案:

SELECT 
r.submission_id,rd.category_id,GROUP_CONCAT(CONCAT('Reviewer ',(SELECT COUNT(*) + 1 
                                  FROM review 
                                  JOIN review_detail ON review.id = review_detail.review_id 
                                  WHERE r.submission_id = review.submission_id 
                                  AND review_detail.category_id = rd.category_id 
                                  AND review_detail.id < rd.id
                                 ),': ',rating,' of review ',review_id) ORDER BY rating SEPARATOR ' / ') AS shorter_column_name
FROM 
review r 
JOIN review_detail rd ON rd.review_id = r.id
GROUP BY r.submission_id,rd.category_id;

返回

+---------------+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
| submission_id | category_id | shorter_column_name                                                                                                                           |
+---------------+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
|             1 |           1 | Reviewer 1:  submission 1.1 cat 1 of review 1 / Reviewer 2:  submission 1.2 cat 1 of review 2 / Reviewer 3:  submission 1.3 cat 1 of review 5 |
|             1 |           2 | Reviewer 1:  submission 1.1 cat 2 of review 1 / Reviewer 2:  submission 1.2 cat 2 of review 2 / Reviewer 3:  submission 1.3 cat 2 of review 5 |
|             2 |           1 | Reviewer 1:  submission 2.1 cat 1 of review 3 / Reviewer 2:  submission 2.2 cat 1 of review 7                                                 |
|             2 |           2 | Reviewer 1:  submission 2.1 cat 2 of review 3 / Reviewer 2:  submission 2.2 cat 2 of review 7                                                 |
|             3 |           1 | Reviewer 1:  submission 3.1 cat 1 of review 4 / Reviewer 2:  submission 3.2 cat 1 of review 6 / Reviewer 3:  submission 3.3 cat 1 of review 8 |
|             3 |           2 | Reviewer 1:  submission 3.1 cat 1 of review 4 / Reviewer 2:  submission 3.2 cat 2 of review 6 / Reviewer 3:  submission 3.3 cat 2 of review 6 |
+---------------+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
,

修复您的查询。

基本问题是表本质上是未排序的,这就是MySQL优化程序删除ORDER BY的原因。

在MySQL中,将所有表放在FROM子句中足以使广告按顺序创建子查询,mysql会保留它。

在Mariadb中这已经足够了,您还添加了LIMIT 18446744073709551615,以便优化程序将其保留

模式(MySQL v5.5)

查询#1

SELECT
    submission_id,category_id,@i,@grp,CONCAT_WS("-",submission_id,category_id) AS catgroup,GROUP_CONCAT(
        CONCAT(
            'Reviewer ',@i := IF(
                @grp = CONCAT_WS("-",category_id),@i := @i + 1,IF(
                    @grp := CONCAT_WS("-",1,1
                )
            ),review_id
        )
    ORDER BY review_id,category_id 
    SEPARATOR ' / '
    ) concatText
FROM
    (SELECT review_id,`rating` FROM review_detail
LEFT JOIN review ON review.id = review_detail.review_id
     ORDER BY review_id,category_id ) t1,(
SELECT
    @i := 0,@grp := ''
) init


GROUP BY
    submission_id,category_id;

结果

| submission_id | category_id | @i  | @grp | catgroup | concatText                                                                                                                                    |
| ------------- | ----------- | --- | ---- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| 1             | 1           | 0   |      | 1-1      | Reviewer 3:  submission 1.1 cat 1 of review 1 / Reviewer 2:  submission 1.2 cat 1 of review 2 / Reviewer 1:  submission 1.3 cat 1 of review 5 |
| 1             | 2           | 3   | 1-1  | 1-2      | Reviewer 3:  submission 1.1 cat 2 of review 1 / Reviewer 2:  submission 1.2 cat 2 of review 2 / Reviewer 1:  submission 1.3 cat 2 of review 5 |
| 2             | 1           | 3   | 1-2  | 2-1      | Reviewer 1:  submission 2.1 cat 1 of review 3 / Reviewer 2:  submission 2.2 cat 1 of review 7                                                 |
| 2             | 2           | 2   | 2-1  | 2-2      | Reviewer 2:  submission 2.1 cat 2 of review 3 / Reviewer 1:  submission 2.2 cat 2 of review 7                                                 |
| 3             | 1           | 2   | 2-2  | 3-1      | Reviewer 2:  submission 3.1 cat 1 of review 4 / Reviewer 1:  submission 3.2 cat 1 of review 6 / Reviewer 3:  submission 3.3 cat 1 of review 8 |
| 3             | 2           | 3   | 3-1  | 3-2      | Reviewer 3:  submission 3.1 cat 1 of review 4 / Reviewer 2:  submission 3.3 cat 2 of review 6 / Reviewer 1:  submission 3.2 cat 2 of review 6 |

View on DB Fiddle

,

您需要使用两步子查询来按审阅者编号排序。

SET @i := 0;
SET @grp := '';
SELECT
    submission_id,GROUP_CONCAT(
      CONCAT(
        'Reviewer ',i,review_id
      )
      ORDER BY i
      SEPARATOR ' / '
    ) concatText
FROM
-- second,add numbering
(
  SELECT *,@i := IF(
      @grp = @grp := CONCAT_WS('-',@i + 1,1) i
  FROM
  -- first,sort for numbering
  (
    SELECT
        review_id,rating
    FROM review_detail LEFT JOIN review ON review.id = review_detail.review_id
    ORDER BY
        submission_id,review_id
  ) t1
) t2
GROUP BY
    submission_id,category_id
;

db fiddle

,

为完整起见,我还添加了解决方案,该解决方案如何在Mysql 8.0中完成

与COUNT(*)一起使用

with base as (
    
  SELECT
    review_id,count(*) over (partition by submission_id,category_id  order by review_id) num
  
    FROM review_detail LEFT JOIN review ON review.id = review_detail.review_id
    ORDER BY
        submission_id,review_id
)
select   
  submission_id,group_concat(concat('Reviewer',num,review_id ) separator ',') concattext
from     base
group by 
submission_id,category_id
;

OR ROW_NUMBER()

with base as (
        SELECT
            review_id,ROW_NUMBER() over (partition by submission_id,category_id  order by review_id) num
        FROM review_detail 
        LEFT JOIN review ON review.id = review_detail.review_id
        ORDER BY
            submission_id,review_id
    )
    SELECT   
        submission_id,review_id  ) separator ',') concattext
    from base
    group by 
        submission_id,category_id
;

DB Fiddle

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res