一尘不染

请任何人帮助我在mysql查询中的情况

sql

我有这个数据。

+------+--------------+------------+
+  id  +  position_id + name       +
+------+--------------+------------+
+  1   +  1           + name_1     +
+  2   +  5           + name_2     +
+  3   +  2           + name_3     +
+  4   +  2           + name_4     +
+  5   +  2           + name_5     +
+  6   +  3           + name_6     +
+  7   +  4           + name_7     +
+  8   +  3           + name_8     +
+  9   +  2           + name_9     +
+------+--------------+------------+

..那我想要结果就像

+--------------+-----------+----------+----------+-----------+
+  position_id +  result1  + result2  +  result3 +  result4  +
+--------------+-----------+----------+----------+-----------+
+  1           +  name_1   +  @       +  @       +  @        +
+  2           +  name_3   +  name_4  +  name_5  +  name_9   +
+  3           +  name_6   +  name_8  +  @       +  @        +
+  4           +  name_7   +  @       +  @       +  @        +
+  5           +  name_2   +  @       +  @       +  @        +
+--------------+-----------+----------+----------+-----------+

我有一些结果数据的案例,这些数据是我的学校报告的。数据结果 必须是动态的,跟随位置的主要位置 ,如果结果 为空,则播种@

有关更多数据或信息,您可以使用以下命令询问


阅读 104

收藏
2021-05-16

共1个答案

一尘不染

如果列数固定,则可以执行以下操作:

SELECT a.position_id, 
        COALESCE(MIN(a.name), '@') AS result1,
        COALESCE(MIN(b.name), '@') AS result2,
        COALESCE(MIN(c.name), '@') AS result3,
        COALESCE(MIN(d.name), '@') AS result4
FROM some_table a
LEFT OUTER JOIN some_table b ON a.position_id = b.position_id AND a.id < b.id
LEFT OUTER JOIN some_table c ON a.position_id = c.position_id AND b.id < c.id
LEFT OUTER JOIN some_table d ON a.position_id = d.position_id AND c.id < d.id
GROUP BY a.position_id

如果列数是可变的,那么如果不根据列数动态创建SQL或使用GROUP_CONCAT做一些令人讨厌的事情,将是不可能实现的。

但这不太可能有效。

进行查询以获得第一个结果,然后在调用脚本中整理格式可能会更好。

编辑

是时候编写一些令人讨厌的代码了,我仍然需要完善!

第一位是存储过程。这样可以得到最大的列数(稍微犯错,但应该很容易进行修复,并且现在可以使用),并动态构建SQL以创建具有此列数的临时表,然后填充它。

DELIMITER ;;
CREATE DEFINER=CURRENT_USER PROCEDURE stored_procedure_name()
BEGIN

    DECLARE sql1 TEXT;
    DECLARE sql2 TEXT;
    DECLARE sql3 TEXT;
    SET @@group_concat_max_len = 32000;

    SELECT 
            GROUP_CONCAT(CONCAT('MIN(a', (1 + units.iCnt + 10 * tens.iCnt), '.name) AS result', (1 + units.iCnt + 10 * tens.iCnt)) ORDER BY (1 + units.iCnt + 10 * tens.iCnt)),
            GROUP_CONCAT(CONCAT('LEFT OUTER JOIN some_table a', (1 + units.iCnt + 10 * tens.iCnt), ' ON  a', (units.iCnt + 10 * tens.iCnt), '.position_id =  a', (1 + units.iCnt + 10 * tens.iCnt), '.position_id AND a', (units.iCnt + 10 * tens.iCnt), '.id <  a', (1 + units.iCnt + 10 * tens.iCnt), '.id') ORDER BY (1 + units.iCnt + 10 * tens.iCnt) SEPARATOR ' '),
            GROUP_CONCAT(CONCAT('result',(1 + units.iCnt + 10 * tens.iCnt), ' VARCHAR(255)') ORDER BY (1 + units.iCnt + 10 * tens.iCnt))
    INTO sql1, sql2, sql3
    FROM
        (
        SELECT MAX(count_name) as max_count_name
        FROM
        (
            SELECT COUNT(name) as count_name
            FROM some_table
            GROUP BY position_id
        ) sub0
    ) sub1,
    (SELECT 1 iCnt UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) units,
    (SELECT 1 iCnt UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) tens
    WHERE max_count_name >= (units.iCnt + 10 * tens.iCnt);

    DROP TEMPORARY TABLE IF EXISTS temp1;

    SET @sqlmain1 = CONCAT('CREATE TEMPORARY TABLE temp1(position_id INT, result0 VARCHAR(255), ', sql3, ')');
    PREPARE stmt FROM @sqlmain1;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    SET @sqlmain2 = CONCAT('INSERT INTO temp1 SELECT a0.position_id, MIN(a0.name) AS result0,', sql1, ' FROM some_table a0 ', sql2, ' GROUP BY a0.position_id ');

    PREPARE stmt FROM @sqlmain2;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;    
END;;
DELIMITER ;

然后,您可以执行此操作,然后从生成的临时表中进行选择。请注意,这两个语句必须在同一SQL会话中完成,否则在执行select时,临时表将消失:

CALL stored_procedure_name();
SELECT * FROM temp1

希望您可以将两者都传递给Jasper。

2021-05-16