こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

HAVING句でのBETWEEN演算子

HAVING句でのBETWEEN演算子の使い方について教えていただけますでしょうか。
MS SQL SERVER のフロントエンドとしてMS ACCESS でパススルークエリを作成中です。
以下のようなテーブルがSQL SERVERにあります。

ID    TIME
AAA   2005/06/01 00:00:10
BBB   2006/02/01 00:00:10
CCC   2006/03/01 00:00:10
AAA   2006/02/01 00:00:10
BBB   2006/02/02 00:00:10
CCC   2006/03/02 00:00:10

MS ACCESS パススルークエリで以下のようなSQL文を作成しました。

SQL文
SELECT ID, TIME
FROM JOB
WHERE TIME between '2006/01/01 00:00:00' and '2006/02/15 23:59:59'

結果
ID    TIME
BBB   2006/02/01 00:00:10
AAA   2006/02/01 00:00:10
BBB   2006/02/02 00:00:10


抽出条件は TIME between '2006/01/01 00:00:00' and '2006/01/31 23:59:59' のままとし、IDをグルーピングしたいと思い以下のように書き換えましたが正しい記述では無いようでエラーとなってしまいます。

SELECT ID, TIME
FROM JOB
GROUP BY CODE
HAVING TIME between '2006/01/01 00:00:00' and '2006/01/31 23:59:59'
ORDER BY ID

欲しい結果
ID
AAA
BBB

正しい記述を教えていただけますでしょうか。
よろしくお願いいたします。

投稿日時 - 2006-03-19 14:05:11

QNo.2038506

困ってます

質問者が選んだベストアンサー

例えば、次のようなJOBのデータがあるとします。

IIDTime
1AAA2005/06/01 0:00:10
2BBB2006/02/01 0:00:10
3CCC2006/03/01 0:00:10
4AAA2006/02/01 0:00:10
5BBB2006/02/02 0:00:10
6CCC2006/03/02 0:00:10

SELECT DISTINCT ID
FROM JOB
GROUP BY ID,time
HAVING TIME between '2006/01/01 00:00:00' and '2006/02/02 23:59:59'
ORDER BY ID

というSQL文の実行結果は...

   |ID  |
---|----
  1|AAA|
  2|BBB|

<SQL Server 2000>

質問者は、かような結果を期待しているのでしょうか?

投稿日時 - 2006-03-20 09:46:58

お礼

ありがとうございます。まさにこれです。

原因1
HAVING句のTIMEはGROUP BYのところにもないといけないということですね。
GROUP BY ID →GROUP BY ID,TIMEに書き換えることでエラーが出なくなりました。

原因2
GROUP BY ID,TIMEと書き換えただけの場合、グルーピングはIDとTIMEをひとつの組み合わせとして行われるので、
IDがユニークとしては表示されなくなるので、DISTINCT IDを実施して重複レコードを削除するんですね。

変更後のSQL文
SELECT DISTINCT ID
FROM JOB
GROUP BY ID,TIME
HAVING TIME between '2006/01/01 00:00:00' and '2006/02/02 23:59:59'
ORDER BY ID

結果
ID
AAA
BBB

なるほどですね。
ありがとうございました。

投稿日時 - 2006-03-20 11:38:41

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

s_husky です。

質問を読み間違っていました。

  |ID  |Time |
---|-----------------------
 1|AAA|2006/02/01 0:00:10|
  2|BBB|2006/02/01 0:00:10|


という結果を欲しているならば...

Select distinct ID , max(time) as time
From job
Where Time > '2006/01/01 23:59:59' and Time < '2006/02/01 23:59:59'
group by id

※指定された範囲に合致するIDを一意に抜き出し、その間のtimeの最大値を取得する。
※これで、事実上、同一の結果が求まると思います。

投稿日時 - 2006-03-20 10:38:48

ANo.1

どういうエラーになったのでしょうか?

GROUP BY指定時、SELECTで選択できるのは、GROUP BYで指定した列か集合関数だけではないでしょうか?

【正】
SELECT C1,COUNT(*)
FROM T1
GROUP BY C1

【誤】
SELECT C1,C2,C3
FROM T1
GROUP BY C1

MySQLではSQLの拡張仕様として、上記の書き方も許していますが、他の殆どのRDBMSではエラーになると思います。

>IDをグルーピングしたいと思い

今の指定では、IDでグループ化した場合、TIMEと対応付けられなくなりますよね?

>SELECT ID, TIME
>FROM JOB
>GROUP BY CODE
>HAVING TIME between '2006/01/01 00:00:00' >and '2006/01/31 23:59:59'
>ORDER BY ID

説明にない列「CODE」でグループ化していますが、「ID」の間違いですか?

「GROUP BY CODE」は、「GROUP BY ID」の間違いと仮定して、SQL例を示します。

【例1】グループ化するIDのみ取り出す
SELECT ID
FROM JOB
GROUP BY ID
HAVING TIME between '2006/01/01 00:00:00' and '2006/01/31 23:59:59'
ORDER BY ID

【例2】TIMEはIDのグループ毎の最大値を取り出す
SELECT ID, MAX(TIME)
FROM JOB
GROUP BY ID
HAVING TIME between '2006/01/01 00:00:00' and '2006/01/31 23:59:59'
ORDER BY ID

投稿日時 - 2006-03-19 20:19:20

補足

>>説明にない列「CODE」でグループ化していますが、「ID」の間違いですか?
すみません。おっしゃるとおり間違いでした。

エラーですが、「TIME は集合関数やGROUP BY句に含まれないのでHAVINGでは有効とならない」と書いてあります。(#8121)
ACCESSの感覚でSQL書いているからだめなんでしょうね。勉強します。

残念ながらいただきましたSQL文でも同様のエラーがでてしまいました。でもアドバイスありがとうございました。

投稿日時 - 2006-03-20 10:28:16

お礼

SELECTの理解不足だったようです。WHERE句で簡単にできることに気がつきました。

SELECT ID
FROM JOB
WHERE TIME between '2006/01/01 00:00:00' and '2006/02/02 23:59:59'
GROUP BY ID
ORDER BY ID

ACCESSだとTIMEを一旦フィールドに入れるのでSQLでも一旦SELECTで選択する必要があると勘違いしていました。
教えていただいたSQL文で気づきました。

ありがとうございました。

投稿日時 - 2006-03-20 11:53:07

あなたにオススメの質問