从mysql中的表创建动态创建的列

从mysql中的表创建动态创建的列,mysql,Mysql,我想创建动态的虚拟列,其中的值是基于联接表生成的 我有一个名为“类型”的下表: id, name 1, TypeA 2, TypeB 我有一张名为category的表格 id, name, type 1, a, 1 2, b, 2 我想要一个返回以下内容的查询 category name, TypeA, TypeB a, 1, 0 b, 0, 1 这可以在mysql中实现吗?有一个名为PIVOT的功能,它可以满足您的需要,但不幸的是,它在mysql中不可用 但是,您可以将所有类型连接到每个

我想创建动态的虚拟列,其中的值是基于联接表生成的

我有一个名为“类型”的下表:

id, name
1, TypeA
2, TypeB
我有一张名为category的表格

id, name, type
1, a, 1
2, b, 2
我想要一个返回以下内容的查询

category name, TypeA, TypeB
a, 1, 0
b, 0, 1

这可以在mysql中实现吗?

有一个名为
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
其中,类别
c
有四种不同的类型,但
a
b
只有一种类型与之关联

如果您事先知道要检查的
类型和数量,并希望在类别中存在该类型时显示布尔值,则可以执行以下操作:

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

有一个名为
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
其中,类别
c
有四种不同的类型,但
a
b
只有一种类型与之关联

如果您事先知道要检查的
类型和数量,并希望在类别中存在该类型时显示布尔值,则可以执行以下操作:

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

我在这里概述几个案例

  • 首先,也是最简单的是:

    但这需要手动提及查询中的所有类型,这显然不是您想要的

  • 可以构建SQL查询并使用它,此方法假设您正在运行来自某个脚本的查询,该脚本可以获取第一个查询的输出并将其用作新查询。

    编写一个小型shell(或其他)脚本应该很容易

  • 在标准SQL中,无法使用表的内容创建语句。不同的数据库为此提供了不同的工具,如
    PIVOT
    语句、过程语言等。我不知道如何使用MySQL工具实现这一点,但想法是动态构建第2点中概述的查询并执行它


  • 我已经介绍了上表中的前两个案例。

    这里我将概述几个案例

  • 首先,也是最简单的是:

    但这需要手动提及查询中的所有类型,这显然不是您想要的

  • 可以构建SQL查询并使用它,此方法假设您正在运行来自某个脚本的查询,该脚本可以获取第一个查询的输出并将其用作新查询。

    编写一个小型shell(或其他)脚本应该很容易

  • 在标准SQL中,无法使用表的内容创建语句。不同的数据库为此提供了不同的工具,如
    PIVOT
    语句、过程语言等。我不知道如何使用MySQL工具实现这一点,但想法是动态构建第2点中概述的查询并执行它


  • 我已经介绍了上的前两个案例。

    您知道您将事先检查多少类型(列)吗?如果是,您是否只想显示布尔值
    0
    1
    (如果该类别存在该类型)?您是否知道您将事先检查多少类型(列)?如果是这样,您是否只想显示布尔值
    0
    1
    (如果类别中存在该类型)?这不是我要寻找的。我想让类型显示为列。所以我想展示的不是“类型”,而是A型,B型。我开始相信这是不可能的。是的,
    PIVOT
    仅适用于Oracle、SQL Server DBMS。你在用什么开发你的应用程序?实际上可以做的一件事是在应用程序逻辑中动态构建查询。首先,您将查询所有类型及其ID,然后您将使用该信息动态地构建一个查询字符串,方法是将有多少个
    LEFT JOIN
    s作为类型进行连接。这样,您就不会在查询中硬编码列选择,但它仍然是一个笨重的解决方案,如果用SQL处理它会更好。我相信另一种解决方案是使用group_concat。因此,对于每个类别,我将显示一个类型列逗号,分隔如下:groupa、type1、type2First solution编辑,以便显示
    group_concat
    字符串中类型的名称。这不是我要找的。我想让类型显示为列。所以我想展示的不是“类型”,而是A型,B型。我开始相信这是不可能的。是的,
    PIVOT
    仅适用于Oracle、SQL Server DBMS。你在用什么开发你的应用程序?实际上可以做的一件事是在应用程序逻辑中动态构建查询。首先,您将查询所有类型及其ID,然后您将使用该信息动态地构建一个查询字符串,方法是将有多少个
    LEFT JOIN
    s作为类型进行连接。这样,你就不难对付科迪了