SQL 旋转和计算存储为字符串的日期之间的差异 - MySQL

SQL pivoting and calculating difference between dates stored as strings - MySQL

我有两个 table。第一个叫 posts,第二个叫 postmeta。 (如果有人注意到,我正在使用一个 Wordpress 数据库,这对于这个任务来说并不重要)。

posts table 看起来像这样(为此缩短)。

ID  |  post_title | post_status | post_type
------------------------------------------
1   |  One        | publish     | hours
2   |  Two        | publish     | hours

postmeta table 看起来像这样。日期格式为 d.m.Y。 G:i:s.

meta_id | post_id | meta_key | meta_value
------------------------------------------
1       | 1       | from     | 1.1.2017. 10:00:00
2       | 1       | to       | 1.1.2017. 16:00:00
3       | 2       | from     | 2.1.2017. 12:00:00
4       | 2       | to       | 2.1.2017. 15:00:00

在那些 table 中 ID = post_id。 想要的结果是下面的 table,其中 date_difffromto 之间的小时差,必须通过 SQL 计算(date_diff = 到 - 从)。请注意,meta_key 定义为 VARCHARmeta_value 定义为 LONGTEXT,这使得计算更加困难。

ID | title | from               | to                 | date_diff
------------------------------------------------------------------
1  | 1     | 1.1.2017. 10:00:00 | 1.1.2017. 16:00:00 | 6
2  | 1     | 2.1.2017. 12:00:00 | 2.1.2017. 15:00:00 | 3

这是我目前拥有的代码。把行变成列对我来说有点问题,计算更麻烦

SELECT posts.ID, posts.post_title, postmeta.meta_key, postmeta.meta_value 
FROM posts
INNER JOIN postmeta 
ON posts.ID = postmeta.post_id
WHERE post_status = 'publish' 
AND post_type = 'hours' 
AND (postmeta.meta_key = 'from' OR postmeta.meta_key = 'to');

非常感谢。 :)

您可以在 postmeta 上使用自连接来获取两个单独的列 使用 str_to_date 转换日期字符串 对保留字使用适当的反引号(例如:from) 和 TIMESTAMPDIFF 获取 diff

的小时数
  SELECT 
          posts.ID
        , posts.post_title
        , str_to_date(table_from.meta_value, '%d.%m.%Y. %H:%i:%s')  as `from` 
        , str_to_date(table_to.meta_value, '%d.%m.%Y. %H:%i:%s' ) as `to` 
        , TIMESTAMPDIFF(HOUR, str_to_date(table_from.meta_value, '%d.%m.%Y. %H:%i:%s') , 
                                    str_to_date(table_to.meta_value, '%d.%m.%Y. %H:%i:%s' )) as diff
  FROM posts
  INNER JOIN postmeta table_from ON posts.ID = table_from.post_id and table_from.meta_key ='from'
  inner join postmeta table_to ON posts.ID = table_to.post_id and table_to.meta_key ='to'
  WHERE post_status = 'publish' 
  AND post_type = 'hours' 

对于小数你可以使用

timestampdiff(MINUTE, startdate, enddate)/60 作为差异

希望对您有所帮助。

SELECT 
   p.id, 
   p.post_title, 
   postmeta_temp.from, 
   postmeta_temp.to, 
   postmeta_temp.date_diff 
FROM   posts p 
   INNER JOIN (SELECT postmeta_from.post_id 
                      AS post_id, 
                      postmeta_from.meta_key 
                                     AS from, 
                      postmeta_to.meta_key 
                                     AS to, 
                      Date_diff(postmeta_to.meta_value, 
                      postmeta_from.meta_value) 
                                     AS date_diff 
               FROM   postmeta postmeta_from 

                      INNER JOIN postmeta postmeta_to 

                              ON postmeta_from.post_id = postmeta_to.post_id 

                                 AND postmeta_from.meta_key = 'from' 

                                 AND postmeta_to.meta_key = 'to') AS 

              postmeta_temp 

           ON p.id = postmeta_temp.post_id 

例如(比 Scaisedge 的方法慢,但更容易阅读...)

DROP TABLE IF EXISTS posts;

CREATE TABLE posts
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,post_title VARCHAR(12) NOT NULL
,post_status VARCHAR(12) NOT NULL
,post_type VARCHAR(12) NOT NULL
);

INSERT INTO posts VALUES
(1,'One','publish','hours'),
(2,'Two','publish','hours');

DROP TABLE IF EXISTS postmeta;

CREATE TABLE postmeta
(meta_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,post_id INT NOT NULL
,meta_key VARCHAR(12) NOT NULL
,meta_value VARCHAR(20) NOT NULL
);

INSERT INTO postmeta VALUES
(1,1,'from','1.1.2017. 10:00:00'),
(2,1,'to'  ,'1.1.2017. 16:00:00'),
(3,2,'from','2.1.2017. 12:00:00'),
(4,2,'to'  ,'2.1.2017. 15:00:00');

-- Date format is d.m.Y. H:i:s.

SELECT post_id
     , MAX(CASE WHEN meta_key = 'from' THEN STR_TO_DATE(meta_value,'%d.%m.%Y. %H:%i:%s') END) `from`
     , MAX(CASE WHEN meta_key = 'to' THEN STR_TO_DATE(meta_value,'%d.%m.%Y. %H:%i:%s') END) `to`
     , TIMEDIFF(
           MAX(CASE WHEN meta_key = 'to' THEN STR_TO_DATE(meta_value,'%d.%m.%Y. %H:%i:%s') END)
         , MAX(CASE WHEN meta_key = 'from' THEN STR_TO_DATE(meta_value,'%d.%m.%Y. %H:%i:%s') END)
               ) date_diff
  FROM postmeta 
 GROUP 
    BY post_id;

+---------+---------------------+---------------------+-----------+
| post_id | from                | to                  | date_diff |
+---------+---------------------+---------------------+-----------+
|       1 | 2017-01-01 10:00:00 | 2017-01-01 16:00:00 | 06:00:00  |
|       2 | 2017-01-02 12:00:00 | 2017-01-02 15:00:00 | 03:00:00  |
+---------+---------------------+---------------------+-----------+

我将最后一部分留作 reader 的(简单)练习。

对于每个 ID,我下次都会使用相同的 ID 和下一个日期进行检查。

select pm.post_id as ID, pm.post_id as title, pm.metavalue as from,  
(select x.metavalue from postmeta x where x.enter code herepost_id = pm.post_id and not x.meta_key = 'from') 
as to , 
(select cast(x.metavalue as timestamp) - cast(pm.metavalue as timestamp) from postmeta x 
      where x.post_id = pm.post_id and not x.meta_key = 'from') as date_diff from 
postmeta pm where pm.meta_key = 'from';


 id | title |        from        |         to         | date_diff 
----+-------+--------------------+--------------------+-----------
  1 |     1 | 1.1.2017. 10:00:00 | 1.1.2017. 16:00:00 | 06:00:00
  2 |     2 | 2.1.2017. 12:00:00 | 2.1.2017. 15:00:00 | 03:00:00