Php 动态MySQL查询:连接来自多个表的结果
这是我一段时间以来遇到的问题。我有一个名为Php 动态MySQL查询:连接来自多个表的结果,php,mysql,sql,join,Php,Mysql,Sql,Join,这是我一段时间以来遇到的问题。我有一个名为gears的表,其中包含名为id、mid、cid和的行。我想搜索此表并以csv格式返回一些唯一的cid的mids列表。例如,如果cid=$cid我可以使用: $query = $database -> query("SELECT COUNT(mid), GROUP_CONCAT(mid) FROM gears WHERE cid=$cid", __LINE__, __FILE__); $gears_installed = $database -&g
gears
的表,其中包含名为id
、mid
、cid
和的行。我想搜索此表并以csv格式返回一些唯一的cid
的mid
s列表。例如,如果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
、lotking
和post
,那么$gears\u安装的将等于3,$gears
将等于bank,lotking,post
。这正是我们想要的
现在谈谈我的问题。每个唯一的mid
都有自己的表,在这里命名为settings\u mid\u
。也就是说,对于以上三个,我有表settings\u bank
,settings\u lotking
,最后是settings\u post
。这些表中的每一个都有一个名为cid
的列(这就是二者之间的关系)。如何运行一个查询,从cid=$cid
的每个表返回整行?我不想对SELECT*FROM settings\u bank其中cid=$cid
和SELECT*FROM settings\u post其中cid=$cid
以及最后SELECT*FROM settings\u post其中cid=$cid
运行单独的查询,因为这可能会导致在一次页面加载中产生大约10个额外的查询(目前有10个不同的mid
s)
正如你所看到的,问题是动态的。它必须能够适应不同数量的mid
s,以某种方式区分每个表中的设置(例如settings\u bank
可能有一个名为name
的列,也可能是settings\u 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
列,以指示该行来自哪个表
或者,您可以动态创建联接:
$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'
这是关系方式。因此,关系数据库管理系统中的R。完全没有理由将数据与元数据混用。如果您这样做,您就可以将关系解决问题转移到应用程序模型的更高级别
最后一件事是:config{mid}
表可能具有相似但不完全相同的结构。也有一个解决方案:
话虽如此,对于您的具体问题,按照Barmar的答案找到一个解决方案就可以了。我有一些想法,但我只能在收集一些方案和一些演示数据以测试查询时提供帮助。否则,这只是一个聪明的猜测。您的意思是,每次gears
表中出现新的mid
时,您都会创建一个新表?使用cid=3@geomagasgears
表可以多次包含特定的mid
。可以说,gears
表将在一个cid
帐户上为每个mid
安装一行。例如,每个mid
都是一个小部件。是的,但我不是这么要求的。假设我在gears
中添加了一行,其中包含一个以前不存在的mid='somewidget'
。我是否也必须创建一个设置\u somewidget
表?我已经为一个测试用例运行了此操作:选择'currency'作为gearname,*来自设置\u currency,其中cid=3
,但这会给出一个错误(由于将'currency'作为gearname
部分)。修复了它。在执行此操作时,MySQL需要在*
之前有一个明确的表名。这非常有效,直到两个表的列数不同(我就是这种情况)-在这一点上,它会崩溃并抛出一个错误。我曾想过做类似于选择一个*,b.*从设置中\u currency a LEFT JOIN settings\u在b.cid=a.cid上发布b,其中a.cid=$cid
,但我不知道如何对多个表执行此操作,现在存在无法将列与其原始表区分开来的问题。例如,将有两列名为name
,一列来自settings\u currency
,另一列来自settings\u post
。我添加了一个连接解决方案。虽然我想知道应用程序将如何处理所有这些动态数据——如果表具有不同的模式,应用程序将如何知道结果中的内容?我最初的想法是使用config
表,但由于每个mid
表都有任意数量的“设置”,因此这是不可能的