我在数据库中有两个表。一个使用索引ID存储用户的名称/详细信息;其他则存储他们编写的文章,仅保留用户ID作为参考(字段 author )。到目前为止,很简单。我可以轻松地查询文章列表,并在查询中包括对用户名称和状态的请求:
SELECT a.name, a.status, s.* FROM articles s, author a WHERE s.author=a.id
问题出在我偶尔获得第二作者称号时,在 author2 字段中引用。到现在为止,我一直在做我假设遍历结果的第二次查询,效率很低,只是从表中获得第二作者的姓名和状态(伪代码):
while ( fetch a row ) {
if (author2 != 0) {
query("SELECT name, status FROM author WHERE id=author2") }
etc. }
尽管这在PHP / MySQL中工作得很好(即使笨拙),但我还是不得不升级到PHP7 / PDO,我想获得无缓冲查询的好处,因此此嵌套查询将不起作用。显然,一种简单的解决方案是先对整个结果进行PDO-> fetchALL(),然后再对foreach循环中的所有结果行进行迭代,并对每行进行这些额外的查询。
但是将第二个数据以某种方式合并到主查询中会更有效,它使用第二个ID( author2 )和主ID从author表中提取,以便在每行中添加 name2 和 status2 字段。我只是看不到该怎么做...
应注意,虽然主要作者ID字段始终为非零,但是如果没有第二个ID,并且在作者表中没有作者ID 0,那么author2字段将包含零,因此任何解决方案都需要通过在这些字段中提供空字符串或某些内容(而不是给出错误)来处理author2 ID为0。 (或者,可以说,可以将具有空数据的虚拟作者ID 0添加到作者表中,这可能不那么优雅)。
任何人都可以建议修改后的原始查询来避免此类二次查询吗?
答案 0 :(得分:2)
从不在FROM
子句中使用逗号。 始终使用正确的,明确的,标准 JOIN
语法。
对于查询,请使用LEFT JOIN
:
SELECT s.*, a1.name, a1.status, a2.name, a2.status
FROM articles s LEFT JOIN
author a1
ON s.author = a1.id LEFT JOIN
author a2
ON s.author2 = a2.id
答案 1 :(得分:0)
戈登·利诺夫(Gordon Linoff)的答案看起来像您所需要的。
我本来可以将此添加为评论,但消息太久了……
我只是对数据库规范化有疑问/评论。会有一个author3的实例吗?如果是这样,那么您可能应该有一个ArticleAuthor表。由于无论如何都在重建代码,因此可以考虑进行改进。
我不知道要存储的信息的名称和数据类型,所以这是我建议的结构的原始示例。
Table Article
ArticleID
ArticleData...
Table Author
AuthorID
AuthorName
AuthorStatus
Table ArticleAuthor
ArticleID
AuthorID
如果状态取决于“作者文章”组合,则AuthorStatus将被移至“ ArticleAuthor”表中。
Table ArticleAuthor
ArticleID
AuthorID
Status