MYSQL帮助 - 操作顺序和子查询

时间:2017-08-08 14:42:32

标签: mysql join subquery max where

我正在使用两个表格(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

通过以下查询,我试图获取每个'facility_id'的指定'reporting_date'的所有提交的列表,其中'list_id'等于1.如果在同一'报告日期发送多个提交',只显示带有最新'时间戳'的提交。

问题:我认为此查询未按照我希望的顺序运行。似乎查询在表中找到每个'facility_id'的最大'时间戳',然后过滤到仅显示具有指定'reporting_date'的提交。我希望它以相反的顺序发生 - 其中查询过滤只显示具有指定'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日,上述查询可以正常运行。

1 个答案:

答案 0 :(得分:0)

这里的答案是使用结构化查询语言的结构化部分。 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。如果该submission_id是自动递增的,则每个工具中报告数据的最大submission_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