我已经绊倒了一段时间了。我有一个名为 gears
的表,其中包含名称为:id
、mid
、cid
和 installed
的行。我想搜索此表并以csv格式返回一些独特cid
的mid
列表。例如,如果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:bank
、lottery
和 post
则$gears_installed
将等于 3,$gears
将等于 bank,lottery,post
。这按预期工作。
现在谈谈我的问题。每个唯一mid
都有自己的表,名为 settings_mid_here
。即以上三个,我有表settings_bank
,settings_lottery
,最后settings_post
。这些表中的每一个还将具有一个名为 cid
的列(这是两者的关联方式)。如何运行一个查询以从cid=$cid
的每个表中返回整行?我不想对SELECT * FROM settings_bank WHERE cid=$cid
和SELECT * 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的答案进行解决方案就可以了。