MySQL IS NULL / IS NOT NULL 오작동?


18

이 표를 살펴보십시오.

mysql> desc s_p;

+-------------------------+------------------+------+-----+---------+----------------+    
| Field                   | Type             | Null | Key | Default | Extra          |
+-------------------------+------------------+------+-----+---------+----------------+
| id                      | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| s_pid                   | int(10) unsigned | YES  | MUL | NULL    |                |
| sm_id                   | int(10) unsigned | YES  | MUL | NULL    |                |
| m_id                    | int(10) unsigned | YES  |     | NULL    |                |
| created                 | datetime         | YES  |     | NULL    |                |
| s_date                  | datetime         | YES  |     | NULL    |                |
| estimated_date          | datetime         | YES  | MUL | NULL    |                |
+-------------------------+------------------+------+-----+---------+----------------+

이제 다음 쿼리를 살펴보십시오.

mysql> select count(*) from s_p where estimated_date is null;
+----------+
| count(*) |
+----------+
|   190580 |
+----------+
1 row in set (0.05 sec)

mysql> select count(*) from s_p where estimated_date is not null;
+----------+
| count(*) |
+----------+
|    35640 |
+----------+
1 row in set (0.07 sec)

mysql> select count(*) from s_p;
+----------+
| count(*) |
+----------+
|  1524785 |
+----------+

위의 개수가 일치하지 않습니다. 내 이해에 따라 :

Where 절없이 쿼리 할 때 Count with IS NULL및 Count with IS NOT NULL는 count와 같아야합니다.

여기서 무슨 일이 일어나고 있는지 아십니까?

===================================================== =

2012 년 2 월 17 일 업데이트

이후 많은 사람들이 추정 된 날짜가 현재 가지고있는 가치에 대해 묻는다는 것을 알았습니다. 답은 다음과 같습니다.

mysql> select distinct date(estimated_date) from s_p;

+----------------------+
| date(estimated_date) |
+----------------------+
| NULL                 |
| 2012-02-17           |
| 2012-02-20           |
| 2012-02-21           |
| 2012-02-22           |
| 2012-02-23           |
| 2012-02-24           |
| 2012-02-27           |
| 2012-02-28           |
+----------------------+
9 rows in set (0.42 sec)

위에서 볼 수 있듯이 추정 된 날짜는 NULL 또는 유효한 날짜 시간 값을 갖습니다. 0 또는 빈 문자열 ""이 없습니다.

추정 날짜의 색인에 문제가있는 경우이 문제가 발생할 수 있습니까?

===================================================== =

2012 년 2 월 18 일 업데이트

다음은 show create 테이블 출력입니다.

 | s_p | CREATE TABLE `s_p` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `s_id` int(10) unsigned DEFAULT NULL,
  `sm_id` int(10) unsigned DEFAULT NULL,
  `m_id` int(10) unsigned DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `estimated_date` datetime DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `sm_id` (`sm_id`),
   KEY `estimated_date_index` (`estimated_date`) USING BTREE,
  ) ENGINE=InnoDB AUTO_INCREMENT=1602491 DEFAULT CHARSET=utf8 |

다시 한 번, 여기서는 추정 날짜의 색인 만 의심 할 수 있습니다.

또한 mysql 서버 버전은 5.5.12입니다.


3
테이블에 3 개의 쿼리를 실행하는 동안 그리고 3 개의 쿼리를 실행하는 동안 새 행이 제공되지 않으면 이런 일이 발생할 수 없습니다!
ypercubeᵀᴹ

6
당신이하고있는 select count(*)것이 select count(estimated_date)아닌가? 이 두 가지가 계산하는 유일한 경우 NULL이 무시되므로 다른 결과를 반환합니다.

6
다음이 MySQL에서 작동하는지 확실하지 않지만 실행할 수 있습니다.-한 번에 SELECT COUNT(*),SUM(CASE WHEN estimated_date IS NULL THEN 1 ELSE 0 END),SUM(CASE WHEN estimated_date IS NOT NULL THEN 1 ELSE 0 END) from s_p모든 수를 가져와야합니다.
Damien_The_Unbeliever

1
이것들은 당신이 실행중인 정확한 쿼리입니까?
gbn

4
또한 이것이 MyISAM이라면 실행할 CHECK TABLE수 있습니까? 엄청나게 큰 전체 행 수를 고려하면 DELETE어딘가에 미친 듯합니다.
Naltharial

답변:


6

날짜가 없습니까? 날짜의 값은 0000-00-00 00:00:00동시에 만족시키기 위해 MySQL이 고려 is null하고 is not null:

steve@steve@localhost > create temporary table _tmp (a datetime not null);
Query OK, 0 rows affected (0.02 sec)

steve@steve@localhost > insert into _tmp values ('');
Query OK, 1 row affected, 1 warning (0.00 sec)

Warning (Code 1264): Out of range value for column 'a' at row 1
steve@steve@localhost > select a from _tmp where a is null;
+---------------------+
| a                   |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)

steve@steve@localhost > select a from _tmp where a is not null;
+---------------------+
| a                   |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)

참조 : http://bugs.mysql.com/bug.php?id=940

이것은 "버그 아님"으로 분류됩니다. 해결 방법을 제안합니다. 엄격 모드를 사용하면 삽입 경고가 오류로 변환됩니다.

이 모든 것을 말하면, 이것만으로 당신이 얻는 결과의 거친 변화를 설명 할 수는 없습니다 ( is nullis not null개수 의 합이 무제한 카운트를 초과해야 함) ...


DATE또는 DATETIME로 정의 된 경우 버그가 나타납니다 NOT NULL. 이 질문에서 열은 nullable로 정의됩니다. 그러나이 버그는 엄격 모드에서만 MySQL을 실행하는 또 다른 이유입니다.
ypercubeᵀᴹ

추정 된 날짜 열의 현재 값을 표시하도록 원래 게시물을 업데이트했습니다. 0000-00-00 또는 빈 문자열 ""이 없습니다.
user1213259

1
@yper 또는 다른 DBMS를 선택해야하는 이유 ...
ErikE

1
@ErikE : 때로는 선택이 아닙니다. 그리고 당신은 항상 당신이 일하고 있든 anotehr DBMS를 선택해야 할 이유를 찾을 것입니다.
ypercubeᵀᴹ

FYI ToadSQL은 0000-00-00 00:00:00을 {null}로 표시하여 물을 더 탁하게합니다! 악몽이야 FTR 문제 열에 대한 색인이 없습니다. 이것은 5.6.15-log에 있습니다.
초에 sming

3

@ypercube :

최근에 회귀 버그 "WHERE 피연산자가 기본 키 또는 고유 인덱스에있을 때 SELECT COUNT (DISTINCT)가 InnoDB와 충돌 함"이라고 생각하는지 물었습니다.

여기 내 대답이 있습니다 (원래 여기) :

http://www.chriscalender.com/?p=315&cpage=1#comment-1460

나는 이것이 같은 버그라고 생각하지 않습니다. 이 버그는 충돌에 대한 자세한 내용이며 특히 SELECT COUNT (DISTINCT)가 필요하며 WHERE 피연산자는 기본 키 또는 고유 인덱스에 있습니다.

버그 / 문제에 DISTINCT가없고 충돌하지 않으며 datetime 열의 인덱스가 기본 키이거나 고유하지 않습니다. 그러나 커프에서 약간 이상하기 때문에 검색을 하고이 버그를 발견했습니다.이 버그는 관련이있을 수 있습니다.

http://bugs.mysql.com/bug.php?id=60105

실제로 "버그 아님"으로 지정되어 있지만 '0000-00-00'으로 날짜 / 날짜 시간이 있고 IS NULL 및 IS NOT NULL을 사용하는 경우 이상한 동작이 발생할 수있는 방법을 보여 주거나 설명합니다.

카운트에 영향을 줄 수있는 이러한 '0000-00-00'행이 있는지 궁금합니다.

버그 보고서에서 언급 한 개발자는이 페이지에 대해서도 언급합니다.

그렇지 않은 경우 5.5.9 이후 9 개월 (및 9 릴리스) 이었으므로 5.5.21 (2012 년 2 월 22 일 현재) 인 최신 5.5에서 업그레이드하고 시도하는 것이 좋습니다 .12 릴리스되었습니다.

테이블과 데이터를 덤프하고 다른 테스트 인스턴스로 가져 와서 테스트 할 수 있어야합니다. 이렇게하면 프로덕션 머신에 영향을 미치지 않으며 몇 분 안에 테스트 인스턴스를 설정할 수 있습니다.

그런 다음 여전히 차이가 없다면 테이블을 MyISAM으로 변환하여 문제가 글로벌 문제인지 또는 InnoDB에만 해당되는지와 같은 다른 항목을 테스트 할 수 있습니다.

또는 'estimated_date'의 색인이 다음과 같은 것으로 나타났습니다.

BTREE 사용 키 estimated_date_index( estimated_date)

“권리 사용”에 유의하십시오. 아마도 BTREE를 사용하지 않고 시도해 보아도 여전히 똑같은 동작이 나타나는지 확인하십시오. (또는 그냥 테스트하기 위해 색인을 모두 제거하십시오. 문제를 좁히는 데 도움이 될 것입니다).

도움이 되었기를 바랍니다.


1

검색어를 사용해보십시오

select * from s_p where estimated_date is null and estimated_date is not null limit 5;

나는 당신이 그 질문이 무엇인지 이해하지 못한다고 생각합니다.

2
위의 쿼리는 솔루션을 찾을 수있는 잘못된 행을 보여줍니다.

1
해당 쿼리가 행을 반환하면 데이터의 무결성에 대해 심각하게 걱정할 것 입니다.
Naltharial

@Naltharial 그것은 내 데이터가 아니며 위의 질문은 이상한 출력을 제공합니다.

mysql> select * from s_p 여기서 추정 _ 날짜는 null이고 추정 _ 날짜는 null 제한이 아닙니다. 5; 빈 세트 (0.00 초)
user1213259

1

테이블 레이아웃에서 '카운트 느낌이 들지 않습니다'라는 흥미로운 내용이 있습니다. 내가 말하려는 것은 직감 일뿐입니다.

전에이 쿼리를 실행했습니다.

select distinct date(estimated_date) from s_p;

COUNT / GROUP BY로 실행

select count(1) rowcount,date(estimated_date) from s_p group by date(estimated_date);

당신은 당신이 찾고있는 결정적인 수를 얻습니다.

그러나 왜 NULL과 NOT NULL의 개수가 올바르게 계산됩니까? 다시, 이것은 단지 교육받은 추측 일뿐입니다.

열이 estimated_date색인화되었습니다. 다음은 내가 시도한 것입니다.

SHOW INDEX FROM s_p;
SHOW INDEX FROM s_p;
SHOW INDEX FROM s_p;
SHOW INDEX FROM s_p;

오타가 아닙니다. SHOW INDEX FROM s_p;네 번 네 번 달리기를 원합니다 . 상기 봐 Cardinality열입니다. s_pInnoDB 의 테이블이므로 카디널리티 열이 매번 다를 것으로 예상합니다. 왜?

InnoDB는 BTREE 페이지 항목을 통해 카운팅하여 카디널리티 값을 계산합니다 (NO PUN INTENDED). 시스템 변수 innodb_stats_on_metadata를 확인하십시오 . 활성화해야합니다. 이미 활성화 된 경우이를 비활성화하고 원래 쿼리를 다시 실행하여 성능이 향상되는지 확인하십시오. 마지막 리조트로만 사용하십시오 !!!

따라서 이러한 쿼리 대신 :

select count(*) from s_p where estimated_date is null;
select count(*) from s_p where estimated_date is not null;

시험

select count(estimated_date) from s_p;

널이 아닌 추정 _ 날짜가있는 행 수를 제공해야합니다.

ISNULL 함수를 사용하여이 무차별 대입 쿼리를 실험 해 볼 수있는 또 다른 방법은 다음과 같습니다 .

select count(*) rowcount,isnull(estimated_date) IsItNull
from s_p group by isnull(estimated_date);

이 제안이 도움이 되길 바랍니다.


-4

이것은 예상됩니다. 널 입력이 가능한 열의 경우 0 == NULL = ""등입니다. 따라서 첫 번째 검사는 실제로 날짜가 설정되지 않았거나 "0 / NULL"과 유사한 행을 반환합니다.


2
0결코 같지 않습니다 NULL. 빈 문자열 ( '')은 NULLOracle로 작업하지 않는 한 어느 것과 동일하지 않습니다 .
ypercubeᵀᴹ
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.