【问题标题】:MYSQL HELP - Order of Operations and Sub QueryMYSQL HELP - 操作顺序和子查询
【发布时间】:2017-08-08 14:42:31
【问题描述】:

我正在使用两个表(ft_form_1 和 ft_field_options)。

ft_form_1

    submission_id  facility_id  admits  reporting_date    timestamp
    1              111A         1       2017-03-31 00:00  2017-03-31 17:53:17
    2              222B         3       2017-03-31 00:00  2017-03-31 18:42:20
    3              333C         6       2017-03-31 00:00  2017-03-31 19:27:47
    4              222B         0       2017-04-01 00:00  2017-04-01 18:12:12
    5              333C         4       2017-03-31 00:00  2017-04-01 19:38:25
    6              333C         5       2017-04-01 00:00  2017-04-01 20:31:16

ft_field_options

    list_id option_order    option_value    option_name
    1       4               111A            New York
    1       2               222B            Chicago
    1       1               333C            Boston
    1       3               444D            Miami

我目前得到的:

    facility_id option_name option_order    admits  reporting_date      timestamp
    111A        New York    3               1       2017-03-31 00:00    2017-03-31 17:53:17

我想得到什么:

    facility_id option_name option_order    admits  reporting_date      timestamp
    111A        New York    3               1       2017-03-31 00:00    2017-03-31 17:53:17
    222B        Chicago     2               3       2017-03-31 00:00    2017-03-31 18:42:20
    333C        Boston      1               4       2017-03-31 00:00    2017-04-01 19:38:25

通过下面的查询,我试图从指定的“报告日期”为每个“设施 ID”获取所有提交的列表,其中“列表 ID”等于 1。如果在同一“报告日期”发送多个提交',只会显示具有最新 'timestamp' 的提交。

问题:我认为此查询未按我希望的顺序运行。似乎查询正在查找表中每个“facility_id”的最大“时间戳”,然后过滤以仅显示具有指定“报告日期”的提交。我希望以相反的顺序发生 - 其中查询过滤以仅显示具有指定“reporting_date”的提交,然后缩小列表以仅显示每个“facility_id”的最大“时间戳”。从我上面的例子可以看出,芝加哥和波士顿被排除在名单之外,因为它们在第二天有一个更新的“时间戳”。

我是 MYSQL 新手,感谢任何帮助!我最初从这个链接中得到了 MAX 子查询的想法:http://www.w3resource.com/sql/aggregate-functions/max-date.php

SELECT t1.facility_id, t1.admits, t1.reporting_date, t1.timestamp, 
t2.option_name, t2.option_order
FROM ft_form_1 t1
LEFT JOIN ft_field_options t2
ON (t1.facility_id = t2.option_value AND t2.list_id = 1)
WHERE (DATE_FORMAT(t1.reporting_date,'%m/%d/%Y') = 
DATE_FORMAT(NOW() - INTERVAL 1 DAY,'%m/%d/%Y')) AND (timestamp=(
SELECT MAX(timestamp)
FROM ft_form_1
WHERE facility_id = t1.facility_id))
ORDER BY option_order ASC

*假设今天是 2017 年 4 月 1 日,上述查询将起作用。

【问题讨论】:

  • 您的问题和示例数据有点混乱,难以理解。您能否仅根据显示的输入向我们展示一个干净的输入表以及您期望的确切输出?
  • 如果您也将日期限制添加到子查询中,它应该可以按预期工作。子查询现在在整个表中搜索最大值,唯一的限制是facility_id,它与顺序或执行无关。
  • 蒂姆,我刚刚清理了一些格式。谢谢!
  • @insider 我认为可行。

标签: mysql join subquery max where


【解决方案1】:

这里的答案是使用结构化查询语言的结构化部分。 SQL 是一种声明性而非程序性语言,因此考虑它做事的顺序。

首先,您要查找 list_id 为 1 的行。让我们进行查询来获得它。注意使用JOIN 而不是LEFT JOIN:我们不想要不匹配的元素。 (http://sqlfiddle.com/#!9/8bdc3c/1/0)

                  SELECT t1.* 
                    FROM ft_form_1 t1
                    JOIN ft_field_options t2 
                            ON t1.facility_id = t2.option_value 
                           AND t2.list_id = 1

接下来,我们需要找到每个设施在每个报告日期的最后一次提交的时间戳。 (http://sqlfiddle.com/#!9/8bdc3c/3/0)

                  SELECT MAX(timestamp) timestamp,
                         reporting_date reporting_date,
                         facility_id 
                    FROM ft_form_1
                   GROUP BY reporting_date, facility_id

这类子查询是不错的选择,因为它们很容易测试。

最后,我们将这两个子查询结合在一起得到我们想要的。 (http://sqlfiddle.com/#!9/8bdc3c/6/0)

SELECT a.*
  FROM (
                  SELECT t1.* 
                    FROM ft_form_1 t1
                    JOIN ft_field_options t2 
                            ON t1.facility_id = t2.option_value 
                           AND t2.list_id = 1
       ) a
  JOIN (
                  SELECT MAX(timestamp) timestamp,
                         reporting_date reporting_date,
                         facility_id 
                    FROM ft_form_1
                   GROUP BY reporting_date, facility_id
       ) b ON a.facility_id = b.facility_id
          AND a.timestamp = b.timestamp
          AND a.reporting_date = b.reporting_date

诀窍在于GROUP BY 子查询,它可以找到每个报告日期的最后一个时间戳。

现在,您的表中有一个submission_id。如果该 submit_id 是自动递增的,那么每个设施中报告数据的最大 submit_id 值很可能就是您想要的值。 如果是这样,您可以大大简化查询。

这将为您提供与您想要的提交相对应的submission_id

                SELECT MAX(submission_id)
                  FROM ft_form_1
                 GROUP BY reporting_date, facility_id

您可以像这样将它加入到您的主表中,以获得您想要的结果。 (http://sqlfiddle.com/#!9/8bdc3c/10/0)

 SELECT t1.* 
   FROM ft_form_1 t1
   JOIN ft_field_options t2 ON t1.facility_id = t2.option_value 
                           AND t2.list_id = 1
   JOIN (
                SELECT MAX(submission_id) submission_id
                  FROM ft_form_1
                 GROUP BY reporting_date, facility_id
        ) q ON t1.submission_id = q.submission_id

【讨论】:

  • 您应该放入自己的 SELECT 和 ORDER BY 子句以获得您需要的确切列。
  • 看起来很整洁。我在哪里可以将报告日期设置为等于某个标准,例如 = DATE_FORMAT(NOW() - INTERVAL 1 DAY,'%m/%d/%Y') ?我可以在底部附近添加另一个 AND 吗?
  • 另外,我不确定我是否理解下面发生的事情。为什么列被引用两次,中间没有逗号。不好意思,慢慢捡mysql... SELECT MAX(timestamp) timestamp,reporting_date reporting_date,facility_id
猜你喜欢
  • 1970-01-01
  • 2013-09-12
  • 2014-07-30
  • 1970-01-01
  • 2014-12-05
相关资源
最近更新 更多