【问题标题】:SESSION group_concat_max_len size is not enough, it gives a different error when changing the sizeSESSION group_concat_max_len 大小不够,改变大小时会出现不同的错误
【发布时间】:2018-09-10 02:22:44
【问题描述】:

所以我在 MySQL 中创建了一个接受整数 _prof_id 的存储过程。此代码用于将我的行动态更改为列。 这是我的代码

DELIMITER $$
CREATE PROCEDURE Get_Attendance(IN _profID INT)
BEGIN
    SET SESSION group_concat_max_len = 18446744073709547520;

    SET @sql = NULL;

    SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(IF(date = ''',
      date,
      ''', status_description, NULL)) AS ',
      date
    )
  ) INTO @sql
      FROM current_att_view;

    SET @sql = CONCAT(
                 'SELECT a.professor_fname, a.professor_lname, ', @sql,  
                  ' FROM professor_tbl m JOIN current_att_view a
                      ON m.professor_id = a.professor_id 
                   WHERE m.professor_id = ', _profID,' Group BY entity_ID');

    PREPARE stmt FROM @sql;
    EXECUTE stmt;
END$$
DELIMITER ;

所以我研究发现 18446744073709547520 是 group_concat_max_len 的最大值,不能无限。但是当我调用该程序时,它给了我一个错误 Mysql Error Image,来自我的表 24th and 25th row of table image 的第 24 行和第 25 行。还有很多行要连接。我该怎么办?或者有没有其他方法可以让我动态地将行更改为列?

所以我的 current_att_view(这是一个创建的视图)结构是current_att_view,教授表结构是这样的Professor Table,我想生成一个查询来生成这样的表结构 Table Structure

当我尝试我的组 concat 代码时,输​​出显示为 output

【问题讨论】:

  • 视图中有多少个不同的日期?
  • 每个学生大约有多少次约会? (最大最小平均)
  • 每学期大约 90+?因为那是出勤,所以必须记录每个日期

标签: mysql concatenation prepared-statement


【解决方案1】:

不是答案,而是扩展评论。此代码在 2016-2017 年的每一天都可以正常工作(尽管速度很慢),即 730 天,这似乎比您需要的要多。我认为这证明我的 64 位盒子上没有 group_concat 截断,其中 max_allowed_pa​​cked 至少默认为 4194304。

drop procedure if exists p;

DELIMITER $$
CREATE PROCEDURE p(IN _profID INT)
BEGIN
    SET SESSION group_concat_max_len = 18446744073709547520;
    #SET SESSION group_concat_max_len = 1024;

    SET @sql = NULL;

set @sql = (
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT('MAX(IF(dte = ', char(39),dte,char(39), ', 1, 0)) AS ', char(39),dte,char(39))
    )
from dates
where year(dte) in(2016,2017)
);
/*
    SET @sql = CONCAT(
                 'SELECT a.professor_fname, a.professor_lname, ', @sql,  
                  ' FROM professor_tbl m JOIN current_att_view a
                      ON m.professor_id = a.professor_id 
                   WHERE m.professor_id = ', _profID,' Group BY entity_ID');
*/
     set @sql = concat('select ',@sql,' from dates;');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
     deallocate prepare stmt;
END$$
DELIMITER ;

call p(1);

【讨论】:

  • 你能澄清一下 char(39),dte,char(39), ', 1, 0)) AS ', char(39),dte,char(39))) 的作用吗?
  • Char(39) 是 ascii 单引号,代码将范围内的所有日期打印为标题,每列的值为 1。
  • 如果我显示 111111111111111 仍然没有问题。
  • 谢谢@P.Salmon!当我将引号更改为 char(39) 时,错误变为 Prepared Statement needs to be re-prepared.. 我尝试添加“DEALLOCATE PREPARE stmt;”执行后,还是什么都没发生
  • 我不喜欢 Group BY entity_ID 因为它是非标准的 sql Group BY a.professor_fname,a.professor_lname 会更好(但可能不是主要问题)。如果你什么也没得到我会怀疑加入什么也没找到——我会调试这个语句,让它为一个已知的教授和日期工作,然后检查准备好的语句是否与工作语句匹配。至于Prepared Statement需要重新准备我不知道解决方案。
【解决方案2】:

这是您的数据的简化版本的猜测

drop table if exists current_att_view,professor_tbl;
create table current_att_view
(attendanceid int auto_increment primary key,
entity_id int,
Professor_id int,
dte date,
status_description varchar(8));

create table professor_tbl
(professor_id int, professor_fname varchar(20), professor_lname varchar(20));

insert into current_att_view (entity_id ,
Professor_id ,
dte ,
status_description) values
(1,1,'2018-01-01','Present'),(1,1,'2018-01-02','Absent'),(1,1,'2018-01-03','Present'),
(2,1,'2018-01-01','Absent'),(2,1,'2018-01-02','Absent'),(2,1,'2018-01-03','Present');

insert into professor_tbl values
(1,'bob','smith'),(2,'fred','jones');

select p.professor_fname,p.professor_lname, dte,status_description
from professor_tbl p
join current_att_view a on a.professor_id = p.professor_id

这个过程

drop procedure if exists p;
DELIMITER $$
CREATE PROCEDURE p(IN _profID INT)
BEGIN
    SET SESSION group_concat_max_len = 18446744073709547520;
    #SET SESSION group_concat_max_len = 1024;

    SET @sql = NULL;

set @sql = (
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT('MAX(IF(dte = ', char(39),dte,char(39), ', status_description , null)) AS ', char(39),dte,char(39))
    )
from current_att_view
);
select length(@sql);

    SET @sql = CONCAT(
                 'SELECT m.professor_lname,m.professor_fname,entity_id ,', @sql,  
                  ' FROM professor_tbl m JOIN current_att_view a
                      ON m.professor_id = a.professor_id 
                   WHERE m.professor_id = ', _profID,' Group BY m.professor_lname,m.professor_fname,entity_id ');

     #set @sql = concat('select ',@sql,' from attendance;');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
     deallocate prepare stmt;
END$$
DELIMITER ;

生成此查询

SELECT m.name,entity_id ,MAX(IF(dte = '2018-01-01', status_description , null)) AS '2018-01-01',
        MAX(IF(dte = '2018-01-02', status_description , null)) AS '2018-01-02',
        MAX(IF(dte = '2018-01-03', status_description , null)) AS '2018-01-03' 
FROM professor_tbl m 
JOIN current_att_view a  ON m.id = a.professor_id 
WHERE m.id = 1 Group BY m.name, a.entity_ID;

这会产生这个结果(如预期的那样)

-----------------+-----------------+-----------+------------+------------+------------+
| professor_lname | professor_fname | entity_id | 2018-01-01 | 2018-01-02 | 2018-01-03 |
+-----------------+-----------------+-----------+------------+------------+------------+
| smith           | bob             |         1 | Present    | Absent     | Present    |
| smith           | bob             |         2 | Absent     | Absent     | Present    |
+-----------------+-----------------+-----------+------------+------------+------------+
2 rows in set (0.01 sec)

我想我不能再帮你了。

【讨论】:

  • 天啊!!太感谢了!!我是多么愚蠢地忘记了 AS PART T.T 之后的单引号谢谢你 sooo muuuch P.Salmon! :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 2016-05-30
  • 2013-01-01
  • 1970-01-01
  • 2012-09-27
  • 2020-02-02
  • 1970-01-01
相关资源
最近更新 更多