質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

2回答

11038閲覧

SQLでvarchar "yyyy-mm" の比較について

skatelomere

総合スコア40

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2017/12/15 05:28

いつもお世話になります。閲覧ありがとうございます。

シンプルな質問です。以下のWHERE句は使用して大丈夫でしょうか?

yyyy_mmはvarchar型です。例えば"2016-02"など。
"5"や"tera123-tail456"などは間違っても入りません。

SQL

1WHERE yyyy_mm < "2017-11" ...

これ実際にやってみると、きちんとyyyy_mm = "2017-09"や"2016-03"などがヒットし、"2017-12"は取得されません。

訳あってDATEやTIMESTAMP型ではなくvarcharでやってるのですが、これだとバグは起こりませんか?
SQLの暗黙の型変換におけるハイフンの影響が単純に不安です。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

SQLの暗黙の型変換におけるハイフンの影響が単純に不安です。

暗黙の型変換は演算時の演算項目の属性に合わせて行われる物です。

項目の名前が日付を意味したものであったり、格納される書式が日付であったとしても、
それで勝手に変換されることはありません。

今回の場合は単に文字列として比較されるのですから、項目に格納される値の書式が統一されている前提であれば問題はありませんね。

追記

yambejpさんへのコメントによると、全体では以下のようなものだと思います。

SQL

1select t2.ym 2from テーブル t1 3 inner join (SELECT DATE_FORMAT(create_time,"%Y-%m") AS ym, ...) t2 4 on t1.xxx=t2.XXX 5where t2.ym < "2017-11" 6group by t2.ym

以下のように、編集前の情報と比較する方がcreate_time をインデックスに含めるなどすれば高速に動作しますし、暗黙の型変換など入る余地もないですね。

SQL

1select t2.ym 2from テーブル t1 3 inner join (SELECT DATE_FORMAT(create_time,"%Y-%m") AS ym, ...) t2 4 on t1.xxx=t2.XXX 5where t2.create_time < cast("2017-11" as DATETIME) 6group by t2.ym

投稿2017/12/15 05:47

編集2017/12/15 08:14
sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

skatelomere

2017/12/15 05:55

回答ありがとうございます。 私の中で「暗黙の型変換」の認識に行き過ぎた点がありました。 「"3+a" > "29" //-> true」というものを、前から比較するだけでなく、「+a部分を無視=削除する」だったり、「+を演算子として考える」などの謎の先入観がありました。 今回のケースでいうと、ハイフンが削れるとか、演算子としての意味を持つとか、そういうものではなかったですね。単純な文字列比較でした。 大切な気づきをありがとうございました。
skatelomere

2017/12/15 06:11

~追記分返信~ そうです、コアはまさにそのクエリです。 いやはや勉強になります、わざわざありがとうございます>< ふと疑問に思ったのですが、インデックスしなくとも文字列比較よりDATE比較の方が速いのでしょうか?(試さずとも速そうな気はしますが…) でもデータが大量になることを考えたら、インデックスがはれる元カラムを基準に比較しておいた方がよさそうですね。今から備えてそうしておきます!
sazi

2017/12/15 08:11

無計画に項目単独のインデックスというのは駄目ですよ。 ちゃんと実行されるSQLの実行計画を見ながら、既存のインデックスに項目追加したり、 新たにマルチカラムでインデックス作成するなどしてチューニングしないと。
sazi

2017/12/15 08:26

>文字列比較よりDATE比較の方が速いのでしょうか? どうでしょう。 varchar(8)とdatetimeではdatetimeの方がサイズは小さいですが、datetimeは小数点を持っているので 相殺されるレベルかもしれません。 ベンチマークなどはおこなっていませんが、感覚的には文字列より高速な気がします。
guest

0

「"2017-09"や"2016-03"」を「"2017/09"や"2016-3"」と
書かなければ先頭から文字列を比較して差異がでた場所から
文字列の大小を判断するので不等号で比較できます。

ただし日付をvarcharで管理するメリットは極めて限られているので
おすすめできませんが

投稿2017/12/15 05:36

yambejp

総合スコア114835

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

skatelomere

2017/12/15 05:45 編集

早速の回答ありがとうございます。単純に文字列比較の原則として考えればいいのですね。 ご指摘頂いたvarchar管理の件ですが、 JOINするテーブルをサブクエリにて「SELECT DATE_FORMAT(create_time,"%Y-%m") AS ym, ... 」のようにして、メインで「GROUP BY ym」として月ごとの集計を得ているため、今回の文字列比較演算が生じていました。 ちなみに実際のcreate_timeの保存はTIMESTAMP型です。 もう少し頭を使えばこの比較は避けられそうな気がするのですが、ymに意図しない数値が入るケースが想定できないので目をつぶっています。。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問