MySQL使用加入问题

时间:2017-10-09 15:56:26

标签: php mysql join

我有一种奇怪的情况。我还没有找到解决方案。我尝试过使用各种连接和子查询,所以我要求一些帮助。我正在使用MySQLi和PHP 7。

我有两张桌子。一个表(称为表)包含人员列表。另一个表包含该人已完成的数据日志,称为报告。

我可以毫无问题地从每个表中清楚地选择所有记录。 我能够使用join语句来仅提取两个表中的记录

我想要完成的是一个查询,它将提取所有记录,但也加入报告表中的数据,同时仅显示报告中的LATEST加入记录(如果适用)。

工作联接查询的示例:

select * from table 

 join reports on (table.ID = reports.ID)
 join contacts on (reports.cID = contacts.cID)

 where date(reports.dTime) = date(curdate()) and reports.Method = $methodID 

无效的修改查询示例。据我所知,我可能需要使用子查询,因为我的逻辑存在缺陷,并且OR不起作用我的想法

select * from table 

 join reports on (table.ID = reports.ID)
 join contacts on (reports.cID = contacts.cID)

 where date(reports.dTime) = date(curdate()) and reports.Method = $methodID OR table.Method = $method

我已尝试按照MySQL文档使用LEFT OUTER JOIN,但似乎无法将其包含在表中的所有记录以及报告中的任何可能数据。

select * from table 

 left outer join reports on (table.ID = reports.ID)

 where date(reports.dTime) = date(curdate()) and reports.Method = $methodID

我做错了吗?或者我对加入缺乏的把握?

感谢您提供的任何帮助。

编辑 - 我刚刚意识到我不可能按报告时间或方法排序或排序,因为那些可能不存在,我不需要能够在此查询中排序。也许按table.timestamp命令。

编辑2 - 添加预期结果的示例:

table
-------------------------------------
firstName | last Name | cID | dTime 
-------------------------------------
Jane      | Doe       | 312 | 10:30am 
John      | Doe       | 318 | 10:35am
Adam      | Doe       |  | 
Berry     | Doe       |  | 
Charlie   | Doe       |  | 

表格表包含有关姓名,年龄等人的各种数据。联系人表格中只包含联系人ID(cid)以及联系人姓名和姓氏。报告表包含dTime和该dTime的cid,它对应于contacts表中的ContactID。联系人ID是唯一的。

2 个答案:

答案 0 :(得分:1)

首先,您应始终提供您使用的真实代码。正如你所看到的(参见@Jay Blanchard的评论),如果你随意发布或更改名字,你会犯错误。

毕竟,你在这里发帖是因为你在某个地方有错误,错误将发生在你不期待它的地方。否则,你会自己找到它。

如果您认为由于某种原因无法披露您的真实代码,那么除了创建a minimal, complete and verifiable example之外别无他法。这是对所有试图帮助的人的态度和尊重。

您展示的代码不会运行,此外,您真的应该告诉我们$method$methodID的来源以及计算方式。

其次,回到你的问题,我注意到一些非常不寻常的事情,哪些可能最终成为一个问题。我不确定,因为你没有显示你的表定义。

对于以下内容,为了明确我想说的内容,让我们假设您的表格table实际上有persons的名称,然后让我们看一下您的表personsreports

通常,在每个表中,您都有一个主键,通常称为ID。当在两个表之间建立关系时,为了使数据库能够建立一个"连接"在两个表的行之间,您必须将另一个表中的一个表的ID值存储在单独的列中

在您的示例中,这意味着表格persons有一列ID而表reports有一列ID,但表reports另外还有一个列PersonID,其中存储了与该行相关的人的ID

但根据你的例子,你是这样加入的:

...
join reports on (persons.ID = reports.ID)
...

如果您使用常用方法并且每个表(包括ID表)中的列reports实际上只是行ID(主键),这没有意义。相反,你必须像这样加入:

...
join reports on (persons.ID = reports.PersonID)
...

第三(或者是母语人士会说"第三个"在这里?),如果你想只提取最后一条记录,你可以使用聚合函数分组。为此,请对SQL语句进行以下更改:

SELECT ...,
       MAX(reports.dTime),
       ...
FROM ...
WHERE ...
GROUP BY persons.ID,
         reports.cID

这将选择PersonIDcID的所有不同对,并显示每个此类对的上一次报告的日期/时间。

如果您希望按PersonID(而不是PersonID / cID对)显示上次报告的日期/时间,则可以从代码中删除最后一行以上。但是请注意,如果您仍然contacts SELECT表中的列,数据库将从contacts表中的匹配行中选择 random

答案 1 :(得分:1)

如果我正确理解数据,下面的查询应该可以获得您正在寻找的结果:

SELECT t.firstName, t.lastName, c.id, r.dTime
FROM Table t
LEFT JOIN reports r ON r.id = t.id
LEFT JOIN contacts c ON c.id = r.cId  

表和报告之间的关系似乎没有正确设置,除非您简化了实际结构。正如Binarus所指出的,您应该在Reports表中有一个tId列,以将Table id存储为外键。