ページ 11

mySqlのhaving句について

Posted: 2010年6月23日(水) 15:34
by ookami
いつもお世話になっております。
mySqlでの質問です。

別スレでお見せしました掲示板について、
その後も可能性をさぐりつつ作り進めているのですが、
行き詰ってしまったところがあります。
一応回避はできるのですが、
どなたか分かりませんでしょうか...

「最小の id を持つレコードを取得する」クエリを投げようと、
最初、以下のようにしました。


[1]
SELECT * FROM T_integmessage having id=min(id)

戻り値なし


ということで、エラーではなかったのですが戻り値が無く、
ちょっと戸惑いつつ、
とりあえず2段階に分け、


[2]
SELECT min(id) FROM T_integmessage

min(id)
-------
10


としてmin(id)を取得してから、
以下のように[1]のmin(id)をマジックナンバー的にしたところ、


[3]
SELECT * FROM T_integmessage having id=10

id text
-- ----
10 なにがし...


と、期待した結果が得られました。

一応、php 側で[2][3]を順に投げるようにすれば回避できますが、
[1]がダメな理由を知りたいのです。
どなたか分かりませんでしょうか...


mysqlサーバのバージョン: 4.0.27

http://dev.mysql.com/doc/refman/4.1/ja/subqueries.html
> MySQL バージョン 4.1 以降では、標準 SQL で規定されているサブクエリのすべての形式と操作に加え、MySQL 固有のいくつかの機能をサポートしています。

ということで、今使っているサーバは4.1より前なので、サブクエリは使えないようです。
実際、 SELECT * FROM T_integmessage having id=(SELECT min(id) FROM T_integmessage)
はエラーでした。

Re:mySqlのhaving句について

Posted: 2010年6月24日(木) 07:34
by toyo
havingの普通の使い方としては
having以下の条件を満たすgroupをselectする
という感じになると思います
select出来るのもgroup byで指定した列か集約関数だけなのでgroup byのないhavingはかなり特殊な使い方になりますね
私としては
SELECT * FROM T_integmessage having id=10
で結果が表示されるほうに違和感を覚えます
検索したところgroup byのないhavingでは例外の発生するデータベースもあるようです
http://www.hitachi.co.jp/Prod/comp/soft ... 070288.HTM

ちなみに最小値の選択の場合、私はソートして最初の列を取得しています

Re:mySqlのhaving句について

Posted: 2010年6月24日(木) 08:47
by ookami
返答ありがとうございます!

>group byのないhavingでは例外の発生するデータベースもあるようです
うーん...そうなんですかね。示されたURLが何のデータベースか、ぱっと分からなかったのですが、
(HITACHI社の特有のデータベースでしょうか?)

mySqlでは以下の記述があります。
http://mysql.oss.eznetsols.org/doc/refm ... tions.html
> GROUP BY 節を含まないステートメントでグループ関数を使用する場合、すべての行をグループ分けするのと同様の効果になります。

ということで、group by が無くてもよいと思うんですよ。

また、
http://mysql.oss.eznetsols.org/doc/refm ... lumns.html
> GROUP BY 節で名付けられていないカラムは、集約関数で使用されていない場合、SELECT リスト、または HAVING 節で利用することができません。
と、微妙な表現がされていますが、これで[1]がダメなら[2]もダメだろうし...

ということで、まだちょっとスッキリしません。すみません。

> ちなみに最小値の選択の場合、私はソートして最初の列を取得しています
確かにそうですね^^;
たまたま[1]から入ったので囚われていました。

Re:mySqlのhaving句について

Posted: 2010年6月24日(木) 12:44
by toyo
HAVINGは単独で使えますがその場合SELECTで意味のあるのは集約関数のみということです
またはテーブル全体がある集約関数を使った条件を満たすかの判断には使えます
SELECT * FROM T_integmessage having max(id) > 20
というクエリで結果が得られればそのテーブルの最大idは20より大きいと判断できます
結果が得られなければ最大idは20以下ということになります
ただ得られた行には何の意味もないでしょう
SELECT * FROM T_integmessage having id=10
ですが集約関数のないHAVINGはWHEREとみなされるのかもしれません
たまたま意図した結果が出ただけかもしれませんので私は使わないほうがいいと思います

Re:mySqlのhaving句について

Posted: 2010年6月24日(木) 14:33
by ookami
お返事ありがとうございます!
ようやく分かってきました。

> 結果が得られればそのテーブルの最大idは20より大きいと判断できます

「MIN」「MAX」と、「<」「>」の組合せ4パターンで、
以下の[4]~[7]のクエリを試してみました。

実際のデータでは、最小のidは10、最大のidは73ですので、
仰るとおりのようです。



[4]
SELECT * FROM T_integmessage HAVING MAX(id)>20

id text
-- ----
11 なにがし...

[5]
SELECT * FROM T_integmessage HAVING MAX(id)<20

戻り値なし

[6]
SELECT * FROM T_integmessage HAVING MIN(id)>20

戻り値なし

[7]
SELECT * FROM T_integmessage HAVING MIN(id)<20

id text
-- ----
11 なにがし...


たしかに、「得られた行には何の意味もない」ようですね。
ここまできて、ようやく最初のお返事の、
「select出来るのもgroup byで指定した列か集約関数だけ」
というのが理解できました。

「ソートして最初の列を取得」する方向で進めようと思います。

これにて「解決!」とさせていただきます。
ありがとうございました!