【问题标题】:Using GROUP BY after calling a stored procedure in MySQL在 MySQL 中调用存储过程后使用 GROUP BY
【发布时间】:2017-10-15 22:40:02
【问题描述】:

我想做这样的事情:

CALL testFunction('26e4ccaa-b125-3d9c-c7c1-58175227a48f')
GROUP BY id_c;

这似乎不起作用,所以我也尝试了这个:

SELECT *
FROM (
   CALL testFunction('26e4ccaa-b125-3d9c-c7c1-58175227a48f')
) t
GROUP BY t.id_c;

这也不起作用。我找不到关于这是否可能的文档。

我在其他地方使用这个存储过程,创建一个全新的存储过程似乎是多余的,这样我就可以包含GROUP BY。我在一个 php 应用程序中调用这个存储过程。

编辑:

这是存储过程:

BEGIN
    DECLARE lastInsertCount INT;
    DECLARE lastLayer INT;
    DROP TABLE IF EXISTS `temp`;
    DROP TABLE IF EXISTS `productGrid`;

    CREATE TABLE `temp`
    (
        `layer` INT(5),
        `title_c` VARCHAR(255), 
        `name` VARCHAR(255), 
        `rep_first_name` VARCHAR(255), 
        `rep_last_name` VARCHAR(255),
        `id_c` CHAR(36),
        `contact_status_reps_c` VARCHAR(255),
        `phone_mobile` VARCHAR(255),
        `contract_type_c` VARCHAR(255),
        `email_address` VARCHAR(255),
        `active_as_of_c` DATETIME,
        `assigned_user_id` CHAR(36)
    );

    CREATE TABLE `productGrid`
    (
        `percentage_c` INT(5),
        `name` VARCHAR(255), 
        `title_c` VARCHAR(255)
    );

    INSERT INTO `productGrid`(`percentage_c`, `name`, `title_c`)
    SELECT aaigloba_crm.pcg_product_comp_grid_cstm.percentage_c, 
           aaigloba_crm.aos_products.name, 
           aaigloba_crm.pcg_product_comp_grid_cstm.title_c
    FROM aaigloba_crm.aos_products_pcg_product_comp_grid_1_c 
        LEFT OUTER JOIN aaigloba_crm.aos_products ON aaigloba_crm.aos_products_pcg_product_comp_grid_1_c.aos_products_pcg_product_comp_grid_1aos_products_ida = aaigloba_crm.aos_products.id
        LEFT OUTER JOIN aaigloba_crm.pcg_product_comp_grid_cstm ON aaigloba_crm.aos_products_pcg_product_comp_grid_1_c.aos_products_pcg_product_comp_grid_1pcg_product_comp_grid_idb = aaigloba_crm.pcg_product_comp_grid_cstm.id_c
    WHERE aaigloba_crm.aos_products_pcg_product_comp_grid_1_c.deleted = '0';

    INSERT INTO `temp`(`layer`, `title_c`, `name`, `rep_first_name`, `rep_last_name`, `id_c`, `contact_status_reps_c`, `phone_mobile`,`contract_type_c`,`email_address`,`active_as_of_c`,`assigned_user_id`)
    SELECT 0,
    wn_writing_number_cstm.title_c, 
    wn_writing_number.`name`, 
    preps_contracted_reps.first_name, 
    preps_contracted_reps.last_name, 
    wn_writing_number_cstm.id_c, 
    preps_contracted_reps_cstm.contact_status_reps_c, 
    preps_contracted_reps.phone_mobile, 
    preps_contracted_reps_cstm.contract_type_c, 
    email_addresses.email_address,
    STR_TO_DATE(preps_contracted_reps_cstm.active_as_of_c, '%m/%d/%Y'),
    wn_writing_number.assigned_user_id
FROM wn_writing_number LEFT OUTER JOIN wn_writing_number_cac_customize_agent_comp_1_c ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing946b_number_ida = wn_writing_number.id
     LEFT OUTER JOIN cac_customize_agent_comp ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing3148nt_comp_idb = cac_customize_agent_comp.id
     LEFT OUTER JOIN cac_customize_agent_comp_cstm ON cac_customize_agent_comp.id = cac_customize_agent_comp_cstm.id_c
     LEFT OUTER JOIN aos_products_cac_customize_agent_comp_1_c ON cac_customize_agent_comp_cstm.id_c = aos_products_cac_customize_agent_comp_1_c.aos_produca2b8nt_comp_idb
     LEFT OUTER JOIN preps_contracted_reps_wn_writing_number_1_c ON preps_contracted_reps_wn_writing_number_1_c.preps_contracted_reps_wn_writing_number_1wn_writing_number_idb = wn_writing_number.id
     LEFT OUTER JOIN preps_contracted_reps ON preps_contracted_reps_wn_writing_number_1_c.preps_cont9effed_reps_ida = preps_contracted_reps.id
     LEFT OUTER JOIN preps_contracted_reps_cstm ON preps_contracted_reps.id = preps_contracted_reps_cstm.id_c
     LEFT OUTER JOIN email_addr_bean_rel ON email_addr_bean_rel.bean_id = preps_contracted_reps_cstm.id_c
     LEFT OUTER JOIN email_addresses ON email_addr_bean_rel.email_address_id = email_addresses.id
     LEFT OUTER JOIN wn_writing_number_cstm ON wn_writing_number_cstm.id_c = wn_writing_number.id
    WHERE wn_writing_number_cstm.wn_writing_number_id_c = passId AND wn_writing_number.deleted = '0' AND preps_contracted_reps.deleted = '0' AND wn_writing_number.deleted = '0' AND email_addr_bean_rel.deleted = '0'
    GROUP BY wn_writing_number.`name`;

    SET lastLayer := 0;
    SET lastInsertCount := 1;
    LayerLoop: WHILE lastInsertCount > 0 DO
      INSERT INTO `temp`(`layer`, `title_c`, `name`, `rep_first_name`, `rep_last_name`, `id_c`, `contact_status_reps_c`, `phone_mobile`,`contract_type_c`,`email_address`,`active_as_of_c`,`assigned_user_id`)
      SELECT lastLayer + 1,
        wn_writing_number_cstm.title_c, 
        wn_writing_number.`name`, 
        preps_contracted_reps.first_name, 
        preps_contracted_reps.last_name, 
        wn_writing_number_cstm.id_c,
        preps_contracted_reps_cstm.contact_status_reps_c, 
        preps_contracted_reps.phone_mobile, 
        preps_contracted_reps_cstm.contract_type_c, 
        email_addresses.email_address,
        STR_TO_DATE(preps_contracted_reps_cstm.active_as_of_c, '%m/%d/%Y'),
        wn_writing_number.assigned_user_id
    FROM wn_writing_number LEFT OUTER JOIN wn_writing_number_cac_customize_agent_comp_1_c ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing946b_number_ida = wn_writing_number.id
         LEFT OUTER JOIN cac_customize_agent_comp ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing3148nt_comp_idb = cac_customize_agent_comp.id
         LEFT OUTER JOIN cac_customize_agent_comp_cstm ON cac_customize_agent_comp.id = cac_customize_agent_comp_cstm.id_c
         LEFT OUTER JOIN aos_products_cac_customize_agent_comp_1_c ON cac_customize_agent_comp_cstm.id_c = aos_products_cac_customize_agent_comp_1_c.aos_produca2b8nt_comp_idb
         LEFT OUTER JOIN preps_contracted_reps_wn_writing_number_1_c ON preps_contracted_reps_wn_writing_number_1_c.preps_contracted_reps_wn_writing_number_1wn_writing_number_idb = wn_writing_number.id
         LEFT OUTER JOIN preps_contracted_reps ON preps_contracted_reps_wn_writing_number_1_c.preps_cont9effed_reps_ida = preps_contracted_reps.id
         LEFT OUTER JOIN preps_contracted_reps_cstm ON preps_contracted_reps.id = preps_contracted_reps_cstm.id_c
         LEFT OUTER JOIN email_addr_bean_rel ON email_addr_bean_rel.bean_id = preps_contracted_reps_cstm.id_c
         LEFT OUTER JOIN email_addresses ON email_addr_bean_rel.email_address_id = email_addresses.id
         LEFT OUTER JOIN wn_writing_number_cstm ON wn_writing_number_cstm.id_c = wn_writing_number.id
      WHERE preps_contracted_reps.deleted = '0' AND wn_writing_number.deleted = '0' AND email_addr_bean_rel.deleted = '0' AND wn_writing_number_cstm.wn_writing_number_id_c IN (SELECT id_c FROM `temp` WHERE layer = lastLayer)
      GROUP BY wn_writing_number.`name`;

      SET lastInsertCount := ROW_COUNT();
      SET lastLayer := lastLayer + 1;
    END WHILE LayerLoop;

    SELECT `title_c`, `name`, `rep_first_name`, `rep_last_name`, `id_c`, `contact_status_reps_c`, `phone_mobile`,`contract_type_c`,`email_address`,`active_as_of_c`,`assigned_user_id`
    FROM `temp`
    ORDER BY rep_first_name ASC;
END

【问题讨论】:

  • 您需要先在表中插入数据。然后你可以对数据进行操作。见上面的链接。
  • 我已经将所有内容存储到存储过程中的临时表中,然后在存储过程结束时使用临时表的选择。我的问题是,你能不能在存储过程之外使用 GROUP BY。
  • 问题出在哪里?如果您的函数返回行,您可以执行 SELECT * FROM yourFunction()
  • 什么? SELECT * FROM testFunction('26e4ccaa-b125-3d9c-c7c1-58175227a48f') 在 MySQL 中不起作用。

标签: php mysql stored-procedures group-by call


【解决方案1】:

GROUP 子句是 SQL 子句,需要合并到完整的 SQL 表达式中,因为 SQL 解析器会自动优化和执行整个表达式。该函数返回一个表,而不是 SQL 表达式,并且 SQL 子句不能修改表。

使用临时表是您在概念上分解您的操作的另一个迹象,可能会对其进行优化。分解是过程代码的好模式,但它是声明性代码的反模式。

您可能已经知道 WHILE 循环在对关系数据的操作中存在问题。太糟糕了,你没有使用 isam 表。

【讨论】:

  • 我认为这回答了我的问题。 “该函数返回一个表,而不是 SQL 表达式,并且 SQL 子句不能修改表。”所以,不,我不能在 CALL 语句之后使用 GROUP BY 语句,尤其是当我的功能是返回一个表。这意味着我要么必须更改我的存储过程,创建一个新的,要么处理 php.ini 中的分组。我想我会做第三个选项。
【解决方案2】:

您的函数需要返回一组记录。

CREATE OR REPLACE FUNCTION testFunction(field1 OUT text, field2 OUT INT)
RETURNS setof record
AS $$ SELECT field1, field2 FROM yourTable $$
LANGUAGE sql;

然后你就可以调用你的函数了

SELECT field1, SUM(field2)
FROM testFunction()
GROUP BY field1

检查这个DEMO

CREATE OR REPLACE FUNCTION dup1(int) 
RETURNS TABLE( f1 text, f2 int) AS 
$$ 
   select f1::text, f2
   FROM ( VALUES ('apple', 3), ('apple', 2), 
                 ('mango', 1), ('pineapple', 3), 
                 ('pineapple', 5) ) T(f1, f2)
$$
LANGUAGE sql;

SELECT f1, SUM(f2)
FROM dup1(1)
GROUP BY f1;

输出

【讨论】:

  • 我的函数确实返回记录。虽然我知道我可以做另一个选择,但我试图看看是否可以在我已经拥有的现有结果集上做一个GROUP BY,而不是做另一个选择。我每次都需要调用该函数,忽略结果,然后进行这个单独的选择,以便我可以对结果进行分组。如果没有,那么 IMO,最好只创建一个包含 GROUP BY 的单独存储过程并使用它。
  • 我不确定是什么问题。我改为RETURN TABLE sintaxis。函数返回数据,可以使用GROUP BY
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
  • 1970-01-01
  • 2017-12-21
相关资源
最近更新 更多