【问题标题】:MySQL filter for specific dates when dates just saved as UNIX timestamp当日期刚刚保存为 UNIX 时间戳时,MySQL 过滤特定日期
【发布时间】:2018-06-05 02:34:23
【问题描述】:

我正在使用 PHP 访问 MySQL 数据库。我有一个这样的表:

表头:

  • id(INT,自动增量),profileid,时间戳

表格内容:

  • 1、12345678、1513814399(= 2017 年 12 月 21 日)
  • 2、13451983、1513814400(= 2017 年 12 月 21 日)
  • 3、12345678、1513944000(= 2017 年 12 月 22 日)
  • 4、12345678、1513944001(= 2017 年 12 月 22 日)

该表显示了网站访问者在何时调用了哪些 profileid。

所以我现在的问题是,如何显示例如: “给我 2017 年 12 月 22 日调用的配置文件号 12345678 的条目数”,在这种情况下为“2”。

我用这个查询试了一下:

SELECT COUNT(profileid), from_unixtime(timestamp, '%d') AS day, from_unixtime(timestamp, '%m') as month, from_unixtime(timestamp, '%Y') as year WHERE profileid='12345678' AND day=22 AND month=12 AND year=2017;

但无法访问“日”、“月”和“年”列,因为它们不存在于表中。

谁能给我一个提示如何做到这一点?另一种方法是创建三个新列(timestamp_day、timestamp_month 和 timestamp_year),但这不是一个好的解决方案。

提前谢谢你!

哈哈

【问题讨论】:

  • “时间戳”字段有什么数据类型?为什么不直接将其设置为“日期”?似乎没有必要将其存储为需要转换才能使用的格式。
  • MySQL 有日期函数,如DAY()MONTH()YEAR(), etc. which you can apply to your date-field. See: dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html
  • 感谢您的 cmets。它具有整数类型。这样做是因为老实说我已经习惯了,而且计算时差很好。

标签: php mysql database date timestamp


【解决方案1】:

这里有一些东西。

  1. 您可以使用FROM_UNIXTIME(timestamp) 将原始时间戳转换为 MySQL TIMESTAMP 对象。你已经知道了。
  2. 拥有TIMESTAMP 后,您可以在其上使用各种日期函数。
  3. 你可以用UNIX_TIMESTAMP()转换其他方向
  4. 当您查找某一天的记录时,您可以进行日期范围搜索。

所以你的查询应该是

   SELECT COUNT(*) cnt
     FROM t
    WHERE profileid = '12345678'
      AND timestamp >= UNIX_TIMESTAMP('2017-12-22')
      AND timestamp <  UNIX_TIMESTAMP('2017-12-23')

这将在您想要的那一天获取每个时间戳值,直到但不包括第二天的午夜。如果您在(profileid, timestamp) 上有索引,这种查询会很快。

注意你也可以这样做

   SELECT COUNT(*) cnt, profileid
     FROM t
    WHERE timestamp >= UNIX_TIMESTAMP('2017-12-22')
      AND timestamp <  UNIX_TIMESTAMP('2017-12-23')
    GROUP BY profileid

并获得一个结果集,显示当天所有配置文件 ID 的计数。而且,你可以这样做

   SELECT COUNT(*) cnt, profileid, DATE(FROM_UNIXTIME(timestamp)) day
     FROM t
    WHERE timestamp >= UNIX_TIMESTAMP('2017-11-01')
      AND timestamp <  UNIX_TIMESTAMP('2017-12-01')
    GROUP BY profileid, DATE(FROM_UNIXTIME(timestamp))

并获得 11 月的一切。

你可以这样做

   SELECT COUNT(*) cnt, profileid, LAST_DAY(FROM_UNIXTIME(timestamp)) month_ending
     FROM t
    WHERE timestamp >= UNIX_TIMESTAMP('2017-01-01')
      AND timestamp <  UNIX_TIMESTAMP('2018-01-01')
    GROUP BY profileid, LAST_DAY(FROM_UNIXTIME(timestamp))

并获得一整年的逐月总结。

日期算术很有用。这就是为什么许多表设计使用实际的类似日期戳的字段,例如 DATETIMETIMESTAMP,而不是原始整数时间戳。

【讨论】:

    【解决方案2】:

    您可以将 MySQL 的 DAYMONTHYEAR 函数与 FROM_UNIXTIME 结合使用。

    SELECT COUNT(profileid)
    WHERE profileid='12345678'
    AND DAY(FROM_UNIXTIME(timestamp))=22
    AND MONTH(FROM_UNIXTIME(timestamp))=12
    AND YEAR(FROM_UNIXTIME(timestamp))=2017;
    

    【讨论】:

      【解决方案3】:

      只需生成日期即可。我想你想要:

      SELECT COUNT(profileid)
      FROM t
      WHERE DATE(from_unixtime(timestamp)) = '2017-12-22' AND
            profileid = '12345678';
      

      我更倾向于这样写:

      SELECT COUNT(profileid)
      FROM t
      WHERE profileid = '12345678' AND
            timestamp >= UNIX_TIMESTAMP('2017-12-22') AND
            timestamp < UNIX_TIMETAMP('2017-12-23');
      

      这允许查询充分利用t(profileid, timestamp) 上的索引。

      【讨论】:

      • 这看起来很棒。不知道可以这样。我会测试它并给你反馈!
      猜你喜欢
      • 1970-01-01
      • 2011-02-08
      • 2012-01-03
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多