高校三年生の合唱祭で何を歌いましたか?

SQL Server 2000 を使用しています。
土日を除いた日数を取得したいと思っていますがわからなくて困っています。
ご助言ください。

あるテーブル(T_Test)に日付列が2つあります。
code|dateA   |dateB
──┼─────┼──────
1  |2010-05-10|2010-05-14
2  |2010-05-14|2010-05-17
3  |2010-05-10|2010-05-28

ここから
code|dateA   |dateB   |日数
──┼─────┼─────┼──
1  |2010-05-10|2010-05-14|4
2  |2010-05-14|2010-05-17|1
3  |2010-05-10|2010-05-28|10

というように土日を除いた datediff のような値を取得したいのです。
datediff で日数を取得でき、datepart で曜日を取得することができるようには
なったのですが、土日を除いた日数を取得(もしくは期間内の土日の日数でも可)を
取得する方法がわかりません。

どうぞ宜しくお願いいたします。

A 回答 (2件)

DATEDIFFは片端ですから、dateAは含まれないということですかね。



計算でも見づらくはなりますが、できることはできますよ。
期間内最初の土曜、日曜をそれぞれ求めて、残りの期間を7で割って回数を求めます。

SELECT
dateA,
dateB,
DATEDIFF(d,dateA,dateB)
-CASE WHEN DATEADD(d,7-DATEPART(dw,DATEADD(d,1,dateA)),DATEADD(d,1,dateA))>dateB THEN 0
ELSE DATEDIFF(d,DATEADD(d,7-DATEPART(dw,DATEADD(d,1,dateA)),DATEADD(d,1,dateA)),dateB)/7+1 END
-CASE WHEN DATEADD(d,8-DATEPART(dw,dateA),dateA)>dateB THEN 0
ELSE DATEDIFF(d,DATEADD(d,8-DATEPART(dw,dateA),dateA),dateB)/7+1 END
FROM T_TEST
    • good
    • 0
この回答へのお礼

jamshid6さん
ありがとうございます。
レコード毎にユーザ定義関数にて計算するよりも早いですね。
回答番号:No.1 の nn1102さんの場合もそうでしたが、[dateA]や[dateB]に時刻まで登録されている場合、単純な DATEDIFF() とは計算結果が異なる場合がありました。
例えば、
[dateA] = #2010/05/19 12:00:00#
[dateB] = #2010/05/20 11:59:59#
だったとすると、DATEDIFF() は 1 となりますが、この場合は 0 となってしまいます。
その点を考慮し、

SELECT dateA,
    dateB,
    DATEDIFF(d, dateA, dateB) - CASE
                   WHEN CAST(CONVERT(varchar, DATEADD(d, 7 - DATEPART(dw, DATEADD(d, 1, dateA)), DATEADD(d, 1, dateA)), 111) AS DATETIME) > dateB THEN 0
                   ELSE DATEDIFF(d, DATEADD(d, 7 - DATEPART(dw, DATEADD(d, 1, dateA)), DATEADD(d, 1, dateA)), dateB) / 7 + 1
                  END
                 - CASE
                   WHEN CAST(CONVERT(varchar, DATEADD(d, 8 - DATEPART(dw, dateA), dateA, 111) AS DATETIME) > dateB THEN 0
                   ELSE DATEDIFF(d, DATEADD(d, 8 - DATEPART(dw, dateA), dateA), dateB) / 7 + 1
                  END
FROM T_Test

としてみました。
お二人ともご助言くださりまして、ありがとうございました!

お礼日時:2010/05/19 15:05

こういったスカラ値関数をつくってやって


CREATE FUNCTION [dbo].[DAYCOUNT](@DATEA DATETIME, @DATEB DATETIME) RETURNS INT
AS
BEGIN

DECLARE @Count INT
SET @Count = 0
DECLARE @CurrentDate DATETIME
SET @CurrentDate = @DATEA

WHILE @CurrentDate <= @DATEB
  BEGIN
    DECLARE @WEEK INT
    SET @WEEK = CAST(DATEPART(WEEKDAY, @CurrentDate) AS INT)
    IF (@WEEK <> 1) AND (@WEEK <> 7)
      BEGIN
        SET @Count = @Count + 1
      END
    SET @CurrentDate = DATEADD(DAY, 1, @CurrentDate)
  END
RETURN @Count
END

それで、SELECT を発行するのはどうでしょうか。
SELECT DATEA, DATEB, dbo.DAYCOUNT(DATEA, DATEB) FROM T_TEST
    • good
    • 0
この回答へのお礼

nn1102さん
ありがとうございます。
ユーザ定義関数を作成する、という発想がなかったです。
ループで日数をカウントってかなり処理に時間がかかりそうで気になったんですが、
実運用で想定されている規模が「総レコード50万件から3万件を抽出する」で
クエリアナライザにてテストすると約6秒でした。思ったよりも早かったです。
(50万件全件抽出だと10分以上かかりました。)
参考にさせていただきます。
ユーザ定義関数を使用せずにやってみる方法も考えてみたいと思います。

お礼日時:2010/05/18 19:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す


おすすめ情報