0

我想创建基于连接表生成值的动态虚拟列。

我有下表称为类型:

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中做吗?

4

2 回答 2

3

我将在这里概述几个案例。

  1. 首先也是最直接的如下:

    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';
    

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

  2. 可以构建 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(或其他)脚本应该很容易。

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

我已经介绍了SQL Fiddle的前 2 个案例。

于 2012-07-01T08:09:34.263 回答
1

有一个特性叫做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有四种不同的类型,但只有一种类型与它们相关联ab

如果您事先知道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
于 2012-07-01T07:34:22.663 回答