【问题标题】:Using array and loop to update MySQL table使用数组和循环更新 MySQL 表
【发布时间】:2021-12-10 05:26:33
【问题描述】:

我有一个包含 3 列的表格

pID | key_name   | value  
-----------------------
10 | 'series'   |'Songs'
10 | 'wood'     |'Beech' 
10 | 'language' |'German'
11 | 'series'   |'Songs'
11 | 'wood'     |'Oak'
11 | 'language' |'French'
12 | 'series'   |'Exams'
12 | 'language' |'English'

我需要更新一个表,其中 key_names 现在是列名,因此

pID | series | wood  | language
-----------------------------
10 ! 'Songs'|'Beech'|'German'
11 | 'Songs'|'Oak'  |'French'
12 | 'Exams'|       |'English'

现在我可以写一些类似的 SQL 了

UPDATE dest-tbl INNER JOIN start-tbl
ON dest-tbl.pID = start-tbl.pID
SET dest-tbl.series = start-tbl.value
WHERE dest-tbl.key_name = 'series'

但由于有 65 个不同的 key_name 值,这意味着该 SQL 必须有 65 个变体。

让我感到震惊的是,最好的方法可能是创建一个 key_name 值的数组并循环遍历它,但我不知道如何做到这一点。

谁能帮我解决这个问题?

使用 MariaDB v10.3

MTIA


编辑: 我想我已经接近下面的 SQL 的答案了。 我确实需要将其插入另一个表并根据另一个表中字段的值过滤结果。从 SELECT 到 GROUP 的代码创建了我需要的输出,但我现在遇到了 JOIN 部分的问题

INSERT INTO results ('series', 'wood', 'language')
SELECT table1.pID, 
MAX(CASE WHEN table1.meta_key = 'series' THEN table1.meta_value END) 'series',
MAX(CASE WHEN table1.meta_key = 'wood' THEN table1.meta_value END) 'wood',
MAX(CASE WHEN table1.meta_key = 'language' THEN table1.meta_value END) 'language'
FROM table1
GROUP BY table1.pID
INNER JOIN ON table2.id = table1.pID
WHERE table2.id.type = 'product';

【问题讨论】:

  • 喜欢枢轴和动态 sql
  • 如果 MySQL 有 PIVOT 函数就可以了。
  • mysql没有pivot功能,所以需要自己构建

标签: arrays loops mariadb


【解决方案1】:
SELECT 
   t1.pID, 
   t1.value,
   t2.value,
   t3.value
FROM Table1 t1
LEFT JOIN Table1 t2 on t2.pID=t1.pID and t2.key_name='wood'
LEFT JOIN Table1 t3 on t3.pID=t1.pID and t3.key_name='language'
WHERE  t1.key_name='series';

输出:

+ -------- + ---------- + ---------- + ---------- +
| 10       | Songs      | Beech      | German     |
| 11       | Songs      | Oak        | French     |
| 12       | Exams      |            | English    |
+ -------- + ---------- + ---------- + ---------- +

DBFIDDLE

【讨论】:

    【解决方案2】:

    正如我在 cmets 中所说,要获得灵活的解决方案,您需要动态 sql

    CREATE TABLE tab1 (
      `pID` INTEGER,
      `key_name` VARCHAR(10),
      `value` VARCHAR(9)
    );
    
    INSERT INTO tab1
      (`pID`, `key_name`, `value`)
    VALUES
      ('10', 'series', 'Songs'),
      ('10', 'wood', 'Beech'),
      ('10', 'language', 'German'),
      ('11', 'series', 'Songs'),
      ('11', 'wood', 'Oak'),
      ('11', 'language', 'French'),
      ('12', 'series', 'Exams'),
      ('12', 'language', 'English');
    
        SET @sql = NULL;
        SELECT
          GROUP_CONCAT(DISTINCT
            CONCAT(
              'max(CASE WHEN `key_name` = ''',
              `key_name`,
              ''' THEN `value` ELSe "" END) AS `',
              
              `key_name`, '`'
            )
          ) INTO @sql
          
          FROM `tab1` ;
    
    SET @sql = CONCAT('SELECT `pID`, ',@sql,' from tab1
    GROUP BY `pID`');
    
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    
    ✓ ✓ 标识符 |语言 |系列 |木头 --: | :------- | :----- | :---- 10 |德语 |歌曲 |榉木 11 |法语 |歌曲 |橡木 12 |英语 |考试 | ✓

    db小提琴here

    【讨论】:

      【解决方案3】:

      我的解决方案,虽然有点慢,但经过测试和工作如下:-

      INSERT INTO results ('series', 'wood', 'language')
      SELECT table1.pID, 
      MAX(CASE WHEN table1.meta_key = 'series' THEN table1.meta_value END) 'series',
      MAX(CASE WHEN table1.meta_key = 'wood' THEN table1.meta_value END) 'wood',
      MAX(CASE WHEN table1.meta_key = 'language' THEN table1.meta_value END) 'language'
      FROM table1, table2
      WHERE table2.ID=table1_pID AND table2.id.type = 'product';
      GROUP BY table1.pID
      

      【讨论】:

        猜你喜欢
        • 2016-01-04
        • 1970-01-01
        • 1970-01-01
        • 2014-01-31
        • 2014-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多