将相似的 meta_key 值分组并使用 meta_value 数据创建结果集

Group similar meta_key values and create result set with meta_value data

我有这样的字段:

meta_key meta_value
schedule_1_date 2021/2/7
schedule_1_lesson 100
schedule_2_date 2020/12/30
schedule_2_lesson 105
schedule_3_date 2021/2/8
schedule_3_lesson 90
schedule_4_date 2021/5/10
schedule_4_lesson 91

我要select满足条件的数据:

例如,在上述条件下,我将得到这些数据:

meta_key meta_value
schedule_1_date 2021/2/7
schedule_1_lesson 100
schedule_3_date 2021/2/8
schedule_3_lesson 90

到目前为止我试过的代码

SELECT * FROM 'table_name' WHERE (meta_key LIKE 'schedule_%_date' AND meta_value IN ('2021/02/07','2021/02/08')) OR (meta_key LIKE 'schedule_%_lesson')

您可以使用 REGEXP 运算符过滤 meta_key 遵循模式 ^schedule_[0-9]+_date$ 的行。在派生的 table 中,还会过滤此类行的 meta_value。使用 replace() 从该行的 meta_key 中删除非数字部分。将派生的 table 加入实际的 table。在 ON 子句中,您可以使用 concat() 和来自派生的 table.[=22= 的 meta_key 的数字部分来构建想要的 meta_keys ]

SELECT t1.meta_key,
       t1.meta_value
       FROM elbat t1
            INNER JOIN (SELECT replace(replace(meta_key,
                                               'schedule_',
                                               ''),
                                       '_date',
                                       '') n
                               FROM elbat t2
                               WHERE t2.meta_key REGEXP '^schedule_[0-9]+_date$'
                                     AND t2.meta_value IN ('2021/2/7',
                                                           '2021/2/8')) n
                       ON t1.meta_key IN (concat('schedule_', n.n, '_date'),
                                          concat('schedule_', n.n, '_lesson'));

db<>fiddle

看看这个:

SELECT tt.meta_key AS lesson_key, tt.meta_value AS lesson_value,
  d.meta_key AS date_key, d.meta_value AS date_value
FROM `table_name` tt
JOIN
  (SELECT t.*, REPLACE(REPLACE(t.meta_key, 'schedule_', ''), '_date', '') AS key_num
  FROM `table_name` t
  WHERE t.meta_key LIKE '%schedule%date%'
    AND t.meta_value IN ('2021/2/7', '2021/2/8')) d
      ON d.key_num = REPLACE(REPLACE(tt.meta_key, 'schedule_', ''), '_lesson', '')
WHERE tt.meta_key LIKE '%schedule%lesson%'

它以稍微不同的格式输出数据,我认为它也可能适用于您:

lesson_key lesson_value date_key date_value
schedule_1_lesson 100 schedule_1_date 2021/2/7
schedule_3_lesson 90 schedule_3_date 2021/2/8

虽然从索引利用率的角度来看,此查询可能不是最佳查询。请务必考虑到这一点。在搜索字符串中间的 LIKE 语句中使用 % 通配符会降低索引的性能。

我假设您对结果集中的 meta_key 没有任何用处,它仅用于分组。

我发现 table 结构对于数据透视查询的设计并不完美,但是通过一些字符串修剪函数,数据透视可以用来简化您的结果集(不需要子查询)。

meta_key 列中第二个下划线之前的字符进行分组。然后使用聚合函数在 SELECT.

中隔离所需的值

DB Fiddle

SELECT 
    MAX(IF(SUBSTRING_INDEX(meta_key, '_', -1) = 'date', meta_value, NULL)) `date`,
    MAX(IF(SUBSTRING_INDEX(meta_key, '_', -1) = 'lesson', meta_value, NULL)) `lesson`
FROM elbat
GROUP BY SUBSTRING_INDEX(meta_key, '_', 2)
HAVING `date` IN ('2021/2/7', '2021/2/8');
date lesson
2021/2/7 100
2021/2/8 90