根据到期时间获取行

时间:2016-02-02 15:34:46

标签: mysql sql

http://sqlfiddle.com/#!9/406cb/2

我有1类,2类,3类,4类的书籍。

  • 第1类 - 将停留1小时
  • 第2类 - 将停留2小时
  • 第3类 - 将停留4小时
  • 第4类 - 将停留6小时

如何编写查询以获得所需结果?

E.g:

  1. 如果当前时间是1454411248,那么它应该显示所有书籍
  2. 如果当前时间是1454414847,那么它不应该显示带有unixtime = 1454411248的类别1书籍(一小时后到期)
  3. 如果当前时间是1454418448,那么类别 - 1,2,3,4到期时间的1,2,4,6小时不应该显示(unix_time将是动态的。我使用静态值例如)。
  4. 等......

    表格

    CREATE TABLE `books` (
        `id` int(255) NOT NULL AUTO_INCREMENT,
        `name` longtext NOT NULL,
        `category` varchar(255) NOT NULL,
        `unix_time` bigint(20) NOT NULL,
        `time_data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=19 ;
    
    
    INSERT INTO `books` (`id`, `name`, `category`, `unix_time`, `time_data`) VALUES
        (1, 'book1', '1', 1454411248, '2016-02-02 05:37:28'),
        (2, 'book2', '2', 1454411248, '2016-02-02 05:37:28'),
        (3, 'book3', '3', 1454411248, '2016-02-02 05:37:28'),
        (4, 'book4', '4', 1454411248, '2016-02-02 05:37:28'),
        (5, 'book5', '1', 1454411248, '2016-02-02 05:37:28'),
        (6, 'book6', '2', 1454411248, '2016-02-02 05:37:28'),
        (7, 'book7', '3', 1454411248, '2016-02-02 05:37:28'),
        (8, 'book8', '4', 1454411248, '2016-02-02 05:37:28'),
        (9, 'book9', '1', 1454497648, '2016-02-03 05:37:28'),
        (10, 'book10', '2', 1454497648, '2016-02-03 05:37:28'),
        (11, 'book11', '1', 1454497648, '2016-02-03 05:37:28'),
        (12, 'book12', '2', 1454497648, '2016-02-03 05:37:28'),
        (13, 'book13', '3', 1454497648, '2016-02-03 05:37:28'),
        (14, 'book14', '4', 1454497648, '2016-02-03 05:37:28'),
        (15, 'book15', '1', 1454497648, '2016-02-03 05:37:28'),
        (16, 'book16', '2', 1454497648, '2016-02-03 05:37:28'),
        (17, 'book17', '3', 1454497648, '2016-02-03 05:37:28'),
        (18, 'book18', '4', 1454497648, '2016-02-03 05:37:28');
    

    查询:

    SELECT *,
        CASE category
            WHEN '1' THEN '1454407648'
            WHEN '2' THEN '1454404048'
            WHEN '3' THEN '1454396848'
            WHEN '4' THEN '1454389648'
        END as category
    from books
    where unix_time >1454411248
    

2 个答案:

答案 0 :(得分:4)

首先,您需要一个表格,将category值与duration值相关联。您可以创建物理表,也可以使用这样的子查询生成虚拟表。

   select 1 as category, 1 as duration UNION ALL
   select 2,2 UNION ALL select 3,4 UNION ALL select 4,6

这会生成以下小查找表。

|| *category* || *duration* ||
||          1 ||          1 ||
||          2 ||          2 ||
||          3 ||          4 ||
||          4 ||          6 ||

接下来,您需要将查找表加入books表,就像这样。此查询还可以包含expiration列,如图所示。

select b.*,
       d.duration,
       FROM_UNIXTIME(unix_time) + INTERVAL d.duration HOUR expiration
  from books b
  join (select 1 as category, 1 as duration UNION ALL
        select 2,2 UNION ALL select 3,4 UNION ALL select 4,6
         ) d ON b.category = d.category

最后,您附加一个WHERE子句来过滤掉未过期的行。

select b.*,
          d.duration,
         FROM_UNIXTIME(unix_time) + INTERVAL d.duration HOUR expiration
  from books b
  join (select 1 as category, 1 as duration UNION ALL
        select 2,2 UNION ALL select 3,4 UNION ALL select 4,6
         ) d ON b.category = d.category
  where FROM_UNIXTIME(unix_time) + INTERVAL d.duration HOUR >= '2016-02-03 08:00:00'

在此示例中,我使用2016-02-03 08:00:00作为当前时间。您可以在生产系统中使用NOW()

使用where子句的sargable版本也很聪明。

   where unix_time >= UNIX_TIMESTAMP('2016-02-03 08:00:00' - INTERVAL d.duration HOUR)

最后,这是一个设计偏好,但混合DATETIME和unix时间戳列有点奇怪。

答案 1 :(得分:2)

创建并填充类别表:

  • category - id,hours_to_live

将图书更改为:

  • book - id,name,category_id,unix_time,time_data

并使用外键category_id引用类别表。

然后你可以通过简单的JOIN实现你想要的东西:

SELECT b.*,
  FROM books b
  JOIN category c
    ON c.id = b.category_id
 WHERE b.unix_time >= NOW() - INTERVAL c.hours_to_live HOUR