【问题标题】:MySQL Partition by Range on YEAR(date) wrong resultsMySQL 按年份(日期)的范围分区错误结果
【发布时间】:2014-06-17 20:10:44
【问题描述】:

我有一个表定义如下:

CREATE TABLE `adverts_stats_clicks` (
 `advert_stats_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
 `advertisment_id` int(10) unsigned NOT NULL DEFAULT '0',
 `domain_id` int(10) unsigned NOT NULL DEFAULT '0',
 `catdom_id` int(10) unsigned NOT NULL DEFAULT '0',
 `added_on` date NOT NULL DEFAULT '0000-00-00',
 `ipfrom` varchar(64) NOT NULL DEFAULT '',
 `click_on` varchar(10) NOT NULL DEFAULT '',
 `click_from` varchar(5) NOT NULL DEFAULT '',
 `click_from_path` char(3) NOT NULL DEFAULT '',
 `country_id` int(11) NOT NULL DEFAULT '0',
 PRIMARY KEY (`advert_stats_id`,`added_on`),
 KEY `domain_id` (`domain_id`),
 KEY `click_on` (`click_on`),
 KEY `advertisment_id` (`advertisment_id`),
 KEY `country_id` (`country_id`),
 KEY `added_on` (`added_on`)
) ENGINE=MyISAM AUTO_INCREMENT=48176808 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (YEAR(added_on))
(PARTITION ac0 VALUES LESS THAN (2005) ENGINE = MyISAM,
PARTITION ac1 VALUES LESS THAN (2006) ENGINE = MyISAM,
PARTITION ac2 VALUES LESS THAN (2007) ENGINE = MyISAM,
PARTITION ac3 VALUES LESS THAN (2009) ENGINE = MyISAM,
PARTITION ac4 VALUES LESS THAN (2010) ENGINE = MyISAM,
PARTITION ac5 VALUES LESS THAN (2011) ENGINE = MyISAM,
PARTITION ac6 VALUES LESS THAN (2012) ENGINE = MyISAM,
PARTITION ac7 VALUES LESS THAN (2013) ENGINE = MyISAM,
PARTITION ac8 VALUES LESS THAN (2014) ENGINE = MyISAM,
PARTITION ac9 VALUES LESS THAN (2015) ENGINE = MyISAM,
PARTITION ac99 VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */

如果我运行以下查询:

SELECT advert_stats_id 
  FROM adverts_stats_clicks 
 WHERE domain_id = 618 
   AND click_on = 'www' 
   AND click_from IN('sel','top','s','e','adv') 
   AND advertisment_id = 6122
   AND added_on BETWEEN '2012-10-01' AND '2014-12-31';

例如,我得到 152 个结果。但是,如果我将日期范围更改为流:

SELECT advert_stats_id 
  FROM adverts_stats_clicks 
 WHERE domain_id = 618 
   AND click_on = 'www' 
   AND click_from IN('sel','top','s','e','adv') 
   AND advertisment_id = 6122
   AND added_on BETWEEN '2013-10-01' AND '2014-12-31';

我得到 643 个结果。这是无稽之谈,因为前一个日期范围大于第二个日期范围。 如果我运行解释分区,我会得到以下信息:

id  select_type     table   partitions  type    possible_keys   key     key_len     ref     rows    Extra   
1   SIMPLE  adverts_stats_clicks    ac7,ac8,ac9 index_merge     domain_id,click_on,advertisment_id,added_on     advertisment_id,domain_id   4,4     NULL    114     Using intersect(advertisment_id,domain_id); Using where

所以在第一个查询中选择了正确的分区(ac7、ac8、ac9)。这证明修剪是有效的。对于第二个查询,也选择了正确的分区(ac8、ac9),但是两者检索到的结果都不可信。

发生了什么???为什么会这样?

来自服务器变量的一些额外信息,以防我可能需要弄清楚。

Variable_name   Value   
character_set_client    utf8mb4
character_set_connection    utf8mb4
character_set_database  latin1
character_set_filesystem    binary
character_set_results   utf8mb4
character_set_server    latin1
character_set_system    utf8
character_sets_dir  /usr/share/mysql/charsets/

如果您需要更多信息以提供帮助,请提供帮助并提出其他问题。

谢谢!

【问题讨论】:

  • 附带说明,您似乎缺少 2008 年的分区。

标签: mysql partitioning


【解决方案1】:

当您使用 BETWEEN '2013-10-01' AND '2014-12-31' 时; 您检查两个字符串之间的值... '2013-10-01' 将作为字符串...

所以如果我们想检查日期之间..字符串应该转换为日期.. 使用 str_to_date() 函数

【讨论】:

  • 完全错误。 '2013-10-01' 是一个有效的日期令牌。它被表示为一个字符串文字,将被 MySQL 正确解析
  • str_to_date 应该用于将字符串转换为日期,当我们想要比较日期时,结果将是错误的..
  • 你说的是错的。在 MySQL 中,字符串文字可以用作日期。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
  • 2010-10-31
  • 2019-02-14
  • 2011-10-07
相关资源
最近更新 更多