动态 MySQL 查询:联接来自多个表的结果


Dynamic MySQL query: Join results from numerous tables

我已经绊倒了一段时间了。我有一个名为 gears 的表,其中包含名称为:idmidcidinstalled 的行。我想搜索此表并以csv格式返回一些独特cidmid列表。例如,如果cid = $cid我可以使用:

$query = $database -> query("SELECT COUNT(mid), GROUP_CONCAT(mid) FROM gears WHERE cid=$cid", __LINE__, __FILE__);
$gears_installed = $database -> get_result($query);
$gears = $database -> get_result($query, 0, 1);

不用担心函数名称,它们完全符合人们的预期。因此,如果该特定$cid有 3 行,其中 mid s:banklotterypost$gears_installed将等于 3,$gears 将等于 bank,lottery,post 。这按预期工作。

现在谈谈我的问题。每个唯一mid都有自己的表,名为 settings_mid_here 。即以上三个,我有表settings_banksettings_lottery,最后settings_post。这些表中的每一个还将具有一个名为 cid 的列(这是两者的关联方式)。如何运行一个查询以从cid=$cid的每个表中返回整行?我不想对SELECT * FROM settings_bank WHERE cid=$cidSELECT * FROM settings_post WHERE cid=$cid运行单独的查询,最后SELECT * FROM settings_post WHERE cid=$cid,因为这可能会导致一个页面加载时大约 10 个额外的查询(目前有 10 个不同的mid)。

如您所见,问题是动态的。它必须能够适应不同数量的mid,以某种方式区分每个表中的设置(例如settings_bank可能有一列名称为 name ,因此可能会settings_post)。最后,如果不存在与给定$cid对应的行,它还必须能够返回默认行(不是空值)。

这是一项复杂的任务,但我希望有人可以帮助我,因为我无法到达任何地方。

$queries = array();
foreach(explode(',', $gears) as $gear) {
    $queries[] = "SELECT '$gear' AS gearname, settings_$gear.* FROM settings_$gear WHERE cid=$cid";
}
$sql = implode(' UNION ', $queries);
$query2 = $database->query($sql);

此查询将为每个表返回一行,并带有一个额外的gearname列来指示该行来自哪个表。

或者,您可以动态创建 JOIN:

$gears_array = explode(',', $gears);
$joins = implode(' JOIN ', $gears_array);
$wheres = implode(' AND ',
                  array_map(function($g) use ($cid) {
                    return "$g.cid = $cid";
                  }, $gears_array));
$sql = "SELECT * FROM $joins WHERE $wheres";
$query2 = $database->query($sql);

这不是您特定问题的答案,仅仅是因为无法通过一个查询完成您正在尝试的操作

原因很简单:RDBMS不是为这种方式工作的。表应该存储表示实体关系的数据。在您的情况下,对于 mid 的每个不同值,必须存在一个名为 settings_{mid} 的表,从而强制mid列隐式存储(表的一部分)。但这不是数据,那是元数据

如果 SQL 语法可以接受变量、参数化、列相关或任意表名,那将不是真正的问题。但事实并非如此。这是设计使然。相反,RDBMS为您提供了将数据相互关联所需的所有工具。通过按预期的方式使用它,您将永远不必诉诸这种"动态"技巧。

在您的情况下,应该有一个带有mid列的config表,以区分引用特定mid值的行。然后,查询将很简单:

select * from `config` where mid='$mid' and cid='$cid'

这是关系方式。因此,RDBMS中的R。绝对没有理由将数据与元数据混合在一起。如果这样做,则将关系解析问题移动到应用程序模型的更高级别。

最后一件事:有人可能会争辩说,config_{mid}表可能具有相似但不相同的结构。对此也有一个解决方案:IS-A关系。

话虽如此,对于您的特定问题,按照Barmar的答案进行解决方案就可以了。