【问题标题】:MySQL Pull All records with join issueMySQL 拉取所有有连接问题的记录
【发布时间】:2017-10-09 15:56:26
【问题描述】:

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

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

我可以毫无问题地从每个表中直接选择所有记录。 我可以使用连接语句仅提取两个表中的记录

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

工作连接查询示例:

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

我做错了什么吗?还是我对 Joins 的掌握不足?

感谢您提供的任何帮助。


编辑 - 我刚刚意识到我不可能按报告时间或方法排序或排序,因为这些可能不存在,我不需要在此查询中排序的能力。也许按 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       |  | 

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

【问题讨论】:

  • 目前还不清楚您要达到的目标。如果您可以添加一些示例数据和预期结果,那将很有帮助。听起来您需要 LEFT JOIN,它将为您提供所有表行,以及连接表中的任何可用信息
  • 我会这样做 - 现在编辑
  • @i-man 我已按要求编辑了问题
  • table是MySQL中的保留字dev.mysql.com/doc/refman/5.5/en/keywords.html
  • 我使用表格作为占位符 - 抱歉。那不是我真正的表名。真正的表名。

标签: php mysql join


【解决方案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 列,以将表 id 存储为外键。

【讨论】:

    【解决方案2】:

    首先,您应该始终提供您使用的真实代码。如您所见(参见@Jay Blanchard 的评论),如果您随意泄露内容或更改名称,您会犯错误。

    毕竟,您在这里发帖是因为您在某处出现错误,而错误将出现在您意想不到的地方。否则,您会自己找到它。

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

    您显示的代码不会运行,此外,您真的应该告诉我们$method$methodID 来自哪里以及您是如何计算它们的。

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

    接下来,为了清楚我想说什么,让我们假设您的表table 实际上具有名称persons,然后让我们看看您的表personsreports

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

    在您的示例中,这意味着表persons 有一个列ID,而表reports 有一个列ID,但表reports 还具有一个列PersonID,其中存储行相关人员的ID

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

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

    如果您使用通常的方法并且每个表(包括reports 表)中的列ID 实际上只是行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 对)显示上次报告的日期/时间,您可以省略上面代码的最后一行。但请注意,如果您仍然是 SELECT contacts 表中的列,那么数据库将从 contacts 表中的匹配行中选择一个 随机 行。

    【讨论】:

    • 感谢您的回复。我会运行一些样本并进行测试,然后再与您联系。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多