有一个下表,名为
fields
:
还有一个专门的表来存储其值,称为
values
我想运行查询以产生以下输出:
Finished | Faculity | Characteristic | Photo
---------------------------------------------
1 | Math | Good |
0 | Biology | Not Good |
我想构建一个输出上述结果的查询。但这并不像看起来那么容易。从这个类似的问题,我尝试运行以下查询:
SELECT flds.id,
(case when flds.name = 'Finished' THEN vals.value END) AS Finished,
(case when flds.name = 'Faculty' THEN vals.value END) AS Faculty,
(case when flds.name = 'Characteristic' THEN vals.value END) AS Characteristic,
(case when flds.name = 'Photo' THEN vals.value END) AS Photo
FROM `values` vals
LEFT JOIN `fields` flds
ON vals.field_id = flds.id
GROUP BY
flds.id,
vals.value;
这给了我意想不到的结果:
有什么办法可以解决吗?
假设对于
field_values
中的每个 id,fields
中的行数相等。也就是说这个查询返回一个1
:
SELECT CASE
WHEN EXISTS(
SELECT 1
FROM(
SELECT COUNT(*) AS cnt
FROM field_values
GROUP BY field_id
) subq
HAVING MAX(subq.cnt) <> MIN(subq.cnt)
)
THEN 0
ELSE 1
END AS test;
否则,解决方案将需要一堆 FULL JOINS 并且会变得混乱。特别是由于 MySQL 没有 FULL JOIN,因此您必须将所有 LEFT/RIGHT ANTI JOIN 与 RIGHT/LEFT JOIN(分别)联合起来。
创建表格并填充示例数据
-- Create your tables
DROP TABLE IF EXISTS fields;
CREATE TABLE fields (id BIGINT NOT NULL
, name VARCHAR(100) NOT NULL
);
INSERT INTO fields(id
, name
)
VALUES(19, 'Finished')
, (20, 'Faculty')
, (21, 'Characteristic')
, (27, 'Photo');
DROP TABLE IF EXISTS field_values;
CREATE TABLE field_values(id BIGINT NOT NULL
, field_id BIGINT NOT NULL
, `value` VARCHAR(100)
);
INSERT INTO field_values(id
, field_id
, `value`
)
VALUES(1, 20, 'Math')
, (2, 21, 'Good')
, (3, 19, '1')
, (4, 27, NULL)
, (5, 20, 'Biology')
, (6, 21, 'Not good')
, (7, 19, '0')
, (8, 27, NULL);
将字段与 field_values 连接,跟踪 field_values 中 id 的顺序。因为我还假设您想使用该值来确定最终的显示顺序。
将此结果与自身连接,以获得最终结果中所需数量的列,并匹配适当的序数位置。
WITH base
AS
(
SELECT fv.id
, fv.`value`
, f.name
, ROW_NUMBER() OVER(PARTITION BY f.id ORDER BY fv.id ASC) AS rn
FROM fields f
INNER JOIN field_values fv
ON f.id = fv.field_id
)
SELECT col1.`value` AS Finished
, col2.`value` AS Faculty
, col3.`value` AS Characteristic
, col4.`value` AS Photo
FROM(
SELECT `value`
, rn
FROM base
WHERE name = 'Finished'
) col1
INNER JOIN (
SELECT `value`
, rn
FROM base
WHERE name = 'Faculty'
) col2
ON col1.rn = col2.rn
INNER JOIN (
SELECT `value`
, rn
FROM base
WHERE name = 'Characteristic'
) col3
ON col2.rn = col3.rn
INNER JOIN (
SELECT `value`
, rn
FROM base
WHERE name = 'Photo'
) col4
ON col3.rn = col4.rn;
自己尝试一下:db<>fiddle