我想创建基于连接表生成值的动态虚拟列。
我有下表称为类型:
id, name
1, TypeA
2, TypeB
我有一个名为类别的表
id, name, type
1, a, 1
2, b, 2
我想要一个返回以下内容的查询
category name, TypeA, TypeB
a, 1, 0
b, 0, 1
这可以在mysql中做吗?
我想创建基于连接表生成值的动态虚拟列。
我有下表称为类型:
id, name
1, TypeA
2, TypeB
我有一个名为类别的表
id, name, type
1, a, 1
2, b, 2
我想要一个返回以下内容的查询
category name, TypeA, TypeB
a, 1, 0
b, 0, 1
这可以在mysql中做吗?
我将在这里概述几个案例。
首先也是最直接的如下:
SELECT c.name AS "CatName",
IF(typea.id IS NULL, 0, 1) AS "TypeA",
IF(typeb.id IS NULL, 0, 1) AS "TypeB"
FROM category c
LEFT JOIN types typea ON c.type = typea.id AND typea.name = 'TypeA'
LEFT JOIN types typeb ON c.type = typeb.id AND typeb.name = 'TypeB';
但这需要手动提及查询中的所有类型,这显然不是您想要的。
可以构建 SQL 查询并使用它,此方法假定您正在从某个脚本运行查询,该脚本可以从第一个查询中获取输出并将其用作新查询。
SELECT concat('SELECT c.name AS "CatName",',
group_concat(concat('IF(',lower(t.name),
'.id IS NULL,0,1) AS "',t.name,'"')),
' FROM category c ',
group_concat(concat('LEFT JOIN types ',
lower(t.name),' ON c.type = ',lower(t.name),'.id AND ',
lower(t.name),'.name = ''',t.name,'''') SEPARATOR ' '),
';')
FROM types t;
编写一个小的 shell(或其他)脚本应该很容易。
在标准 SQL 中,不可能使用表的内容来创建DML语句。不同的数据库为此提供了不同的工具,如PIVOT
语句、过程语言等。我不知道如何使用 MySQL 工具来实现这一点,但想法是动态构建第 2 点中概述的查询并执行它。
我已经介绍了SQL Fiddle的前 2 个案例。
有一个特性叫做PIVOT
可以做你想做的事,但不幸的是,它在 MySQL 中不可用。
但是,您可以做的是将所有类型连接到每个类别的单个字符串中:
SELECT
a.name,
GROUP_CONCAT(b.name) AS types
FROM
category a
LEFT JOIN
types b ON a.type = b.id
GROUP BY
a.id
这将导致类似:
name | types
--------------------------------
a | TypeA
b | TypeB
c | TypeA,TypeB,TypeC,TypeD
其中 categoryc
有四种不同的类型,但只有一种类型与它们相关联a
。b
如果您事先知道type
要检查的 s 和数量,并且希望在该类别存在该类型的情况下显示一个布尔值,您可以这样做:
SELECT,
a.name,
b.id IS NOT NULL AS TypeA,
c.id IS NOT NULL AS TypeB,
-- etc...
FROM
category a
LEFT JOIN
types b ON a.type = b.id AND b.id = 1
LEFT JOIN
types c ON a.type = c.id AND c.id = 2
-- etc...
编辑:如果您事先不知道要创建的列数,但仍希望在它们自己的单独列中为每种类型提供布尔值,则另一种选择是在应用程序逻辑中动态构建查询字符串。假设您使用的是 PHP,例如:
$columns = $ljoins = array();
$i = 1;
foreach($pdo->query('SELECT id, name FROM types') as $row)
{
$columns[] = "t$i.id IS NOT NULL AS " . $row['name'];
$ljoins[] = "LEFT JOIN types t$i ON a.type = t$i.id AND t$i.id = " . $row['id'];
$i++;
}
$sql = 'SELECT a.name, ' . implode(', ', $columns) . ' FROM category a ' . implode(' ', $ljoins);
$stmt = $pdo->query($sql);
// Do stuff with result-set