Mysql 5.6 timestampdiff проблема с возвращаемым результатом - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть две таблицы

CREATE TABLE `contract` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`emp_id` int(11) DEFAULT NULL ,
`sign_time` datetime DEFAULT NULL ,
`end_time` datetime DEFAULT NULL ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

CREATE TABLE `employee_detail` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL ,
 `stage` varchar(100) DEFAULT NULL ,
 PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

и некоторые данные:

INSERT INTO `contract` (`id`, `emp_id`,`sign_time`, `end_time`) VALUES 
('25', '83', '2018-11-21 00:00:00', '2018-12-01 15:27:00');
INSERT INTO `contract` (`id`, `emp_id`,`sign_time`, `end_time`) VALUES 
('26', '94', '2018-11-21 00:00:00', '2018-12-01 15:23:00');

INSERT INTO `employee_detail` (`id`, `name`, `stage`) VALUES ('83', 'Michael', 
'1');
INSERT INTO `employee_detail` (`id`, `name`, `stage`) VALUES ('94', 'John', 
'1');

, когда я запрашиваю базу данных с помощью SQL:

SELECT
c.*
FROM
contract c
JOIN employee_detail e ON c.emp_id = e.id
WHERE
   e.stage != - 1
AND (
TIMESTAMPDIFF(
    MINUTE,
    '2018-11-30 09:18:23',
    c.end_time
)
) > 0
AND TIMESTAMPDIFF(
MONTH,
'2018-11-30 09:18:23',
c.end_time
) = 0

Я получил 0 записей,Но если я сделаю запрос с помощью SQL:

 SELECT
c.*
FROM

contract c
JOIN employee_detail e ON c.emp_id = e.id
WHERE
   e.stage != - 1
AND (
TIMESTAMPDIFF(
    MINUTE,
    '2018-11-30 09:18:23',
    c.end_time
)
) > '0'
AND TIMESTAMPDIFF(
MONTH,
'2018-11-30 09:18:23',
c.end_time
) = '0'

, который превращает целое число 0 в строку '0', я получаю две правильные записи.Я искал из https://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_timestampdiff, и обнаружил, что:

Возвращает datetime_expr2 - datetime_expr1, где datetime_expr1 и datetime_expr2 являются выражениями date или datetime.Одно выражение может быть датой, а другое датой-временем;значение даты рассматривается как дата-время, имеющее, где необходимо, часть времени «00: 00: 00».Единица для результата ( целое число ) задается аргументом единицы.Допустимые значения для unit такие же, как те, которые перечислены в описании функции TIMESTAMPADD ().

Я не совсем понимаю результат и объяснение Oracle.Таким образом, функция timestampdiff возвращает одно целочисленное значение, но когда я использую его в выражении SQL, я получаю неверный результат, в то время как, если я рассматриваю его как строковое значение, я получаю правильный ответ.Кто-нибудь может объяснить странное явление?Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Я получаю противоречивые результаты в зависимости от того, какой предикат используется первым в запросе:

SELECT
    c.*
    , TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time)  diff_month1
    , case when TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time) = 0 then 'equal'
           when TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time) > 0 then 'greater'
      end diff_month
    , TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) diff_minute1
    , case when TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) = 0 then 'equal'
           when TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) > 0 then 'greater'
      end diff_minute
FROM contract c
JOIN employee_detail e ON c.emp_id = e.id
where TIMESTAMPDIFF(MONTH ,'2018-11-30 09:18:23',c.end_time) = 0
  and TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) = 0
id | emp_id | sign_time           | end_time            | diff_month1 | diff_month | diff_minute1 | diff_minute
-: | -----: | :------------------ | :------------------ | ----------: | :--------- | -----------: | :----------
25 |     83 | 2018-11-21 00:00:00 | 2018-12-01 15:27:00 |           0 | equal      |         1808 | greater    
26 |     94 | 2018-11-21 00:00:00 | 2018-12-01 15:23:00 |           0 | equal      |         1804 | greater    
SELECT
    c.*
    , TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time)  diff_month1
    , case when TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time) = 0 then 'equal'
           when TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time) > 0 then 'greater'
      end diff_month
    , TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) diff_minute1
    , case when TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) = 0 then 'equal'
           when TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) > 0 then 'greater'
      end diff_minute
FROM contract c
JOIN employee_detail e ON c.emp_id = e.id
where TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) = 0
  and TIMESTAMPDIFF(MONTH ,'2018-11-30 09:18:23',c.end_time) = 0
id | emp_id | sign_time | end_time | diff_month1 | diff_month | diff_minute1 | diff_minute
-: | -----: | :-------- | :------- | ----------: | :--------- | -----------: | :----------

db <> fiddle здесь

Это испытание в MySQL 8.0, но я получаю такое же несоответствие в MySQL 5.7.12 при использовании rextester.com

0 голосов
/ 03 декабря 2018

Вы не должны проверять, будет ли запись в указанном временном диапазоне, как это, поскольку MySQL не будет использовать индексы в этом случае.Попробуйте изменить часть const и сравнить с колонкой.Примерно так:

ГДЕ

       e.stage != - 1
   AND c.end_time < DATE_SUB('2018-11-30 09:18:23', INTERVAL 1 MINUTE)
   AND c.end_time > DATE_SUB('2018-11-30 09:18:23', INTERVAL 1 MONTH)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...