从2个表中选择可能具有相应日期的

时间:2019-01-15 10:34:34

标签: mysql

我正在为我的mysql数据库寻找正确的查询,该数据库具有2个单独的长度和重量表。 我希望将结果作为1列3列查询返回:日期时间,长度和重量。 该查询还应允许指定用户。 例如:

桌子高度:

id  user_id  created_on           height 
 1  2        2019-01-01 00:00:01  180  
 2  2        2019-01-02 00:00:01  181  
 3  3        2019-01-03 00:00:01  182  
 4  3        2019-01-04 00:00:01  183  
 5  2        2019-01-07 00:00:01  184  

表重:

 id  user_id  created_on           weight
 1   2        2019-01-01 00:00:01  80   
 2   2        2019-01-04 00:00:01  81   
 3   3        2019-01-05 00:00:01  82   
 4   3        2019-01-06 00:00:01  83   
 5   2        2019-01-07 00:00:01  84  

我希望通过一个查询获得以下结果:

user_id  created_on             weight  height 
2        2019-01-01 00:00:01    80      180  
2        2019-01-02 00:00:01    null    181  
2        2019-01-04 00:00:01    81      null  
2        2019-01-07 00:00:01    84      184  

我曾尝试使用JOIN语句,但未能获得所需的结果。 此连接语句

SELECT w.* , h.* FROM weight w 
  JOIN height h 
    ON w.created_on=h.created_on
    AND w.user_id=h.user_id AND user_id=2

将仅返回同时包含user_id和created_on的身高和体重项目的那些结果 完全外部联接可以解决问题,但是mysql不支持。 以下查询似乎正在返回所需的结果,但是它非常慢:

SELECT r.* FROM 
    (SELECT w.user_id as w_user, w.created_on as weightdate, w.value as weight, h.created_on as heightdate ,h.user_id as h_user, h.value as height FROM weight w
    LEFT JOIN height h ON w.user_id = h.user_id 
    AND w.created_on=h.created_on 
    UNION 
    SELECT w.user_id as w_user, w.created_on as weightdate, w.value as weight, h.created_on as heightdate ,h.user_id as h_user, h.value as height FROM weight w
    RIGHT JOIN height h ON w.user_id = h.user_id 
    AND w.created_on=h.created_on ) r 
WHERE h_user=2 OR w_user =2

如果2个表具有大约3000个条目,则查询将花费3秒钟以上的时间。 有没有办法加快速度,可能使用其他方法?

要获得额外的奖励积分:是否可以在两个created_on日期时间之间留出一点时间差异? (例如10分钟或同一小时内)。例如。如果列权重在2019-01-01 00:00:00处有一个条目,而表格高度在2019-01-01 00:04:00处有一个高度的条目,则它们出现在同一行。

2 个答案:

答案 0 :(得分:1)

您可以使用@AutowireUNIONheights表中选择所有不同的日期,而不是使用日历表选择感兴趣的日期。要处理彼此在一小时内的匹配时间,可以使用weights比较时间并将TIMESTAMPDIFF时间截断为该小时。由于这可能会创建重复的条目,因此我们在查询中添加了created_on限定词:

DISTINCT

输出(从我的演示中,我修改了您的时间以允许在一小时内进行匹配):

SELECT DISTINCT COALESCE(h.user_id, w.user_id) AS user_id,
       DATE_FORMAT(COALESCE(h.created_on, w.created_on), '%y-%m-%d %H:00:00') AS created_on,
       w.weight,
       h.height
FROM (SELECT created_on FROM heights
      UNION
      SELECT created_on FROM weights) d
LEFT JOIN heights h ON ABS(TIMESTAMPDIFF(HOUR, h.created_on, d.created_on)) = 0 AND h.user_id = 2
LEFT JOIN weights w ON ABS(TIMESTAMPDIFF(HOUR, w.created_on, d.created_on)) = 0 AND w.user_id = 2
WHERE h.user_id IS NOT NULL OR w.user_id IS NOT NULL
ORDER BY created_on

Demo on dbfiddle

答案 1 :(得分:0)

这可能最好使用日历表来处理,该表包含查询的所有感兴趣的日期。我们可以从日历表开始查询,然后左移到身高和体重表:

SELECT
    COALESCE(h.user_id, w.user_id) AS user_id,
    d.dt AS created_on,
    w.weight,
    h.height
FROM
(
    SELECT '2019-01-01 00:00:01' AS dt UNION ALL
    SELECT '2019-01-02 00:00:01' UNION ALL
    SELECT '2019-01-03 00:00:01' UNION ALL
    SELECT '2019-01-04 00:00:01' UNION ALL
    SELECT '2019-01-05 00:00:01' UNION ALL
    SELECT '2019-01-06 00:00:01' UNION ALL
    SELECT '2019-01-07 00:00:01'
) d
LEFT JOIN heights h
    ON d.dt = h.created_on AND h.user_id = 2
LEFT JOIN weights w
    ON d.dt = w.created_on AND w.user_id = 2
WHERE
    h.user_id IS NOT NULL OR w.user_id IS NOT NULL
ORDER BY
    d.dt;

enter image description here

Demo