2009-05-11 9 views
2

月の最初の 'N'日に支払われたすべての請求書を計算する必要があります。私は2つのテーブルを持っています与えられた月の最初の就業日をSQLで計算する

請求書:請求書情報があります。重要なフィールドは「datePayment」と呼ばれます

HOLYDAYS:1つの列テーブルです。この表のエントリは、「2009-01-01」、「 2009-05-01」などの形式です。

土曜日と日曜日も考慮する必要があります。 (これは問題ありません。 neccesary場合hollidaysとしてそれらを考慮するために、Hollidaysテーブルで当時)

問題は「支払限度」でどの計算することです。

select count(*) from invoice 
where datePayment < PAYMENTLIMIT 

私の質問は、このPAYMENTLIMITを計算する方法である。ここで、お支払いは「毎月第5営業日」です

クエリはMysqlとOracleで実行する必要があります。したがって、標準SQLを使用する必要があります。

ヒント?

EDIT 質問のタイトル疑似クエリと一致させるためには、のようになり、次のとおりです。

select count(*) from invoice 
where datePayment < FIRST_WORKING_DAY + N 

を、その後の質問は毎月のFIRST_WORKING_DAYを計算するために減少させることができます。このような

+2

に正しいスペルを取得するには2つのチェックが必要あなたの2番目のテーブルの "休日" –

+2

実際には、テーブルは 'Feiertag'と呼ばれています。 :-)とにかく、コメントのおかげで。それを修正します。 – Luixv

+0

あなたの質問が何であるか理解できません。毎月の最初の就業日や支払限度額の見方を知りたいですか?お支払いは最初の営業日+ 5営業日かかりますか? –

答えて

2

何かがうまくいくかもしれない:

create function dbo.GetFirstWorkdayOfMonth(@Year INT, @Month INT) 
returns DATETIME 
as begin 
    declare @firstOfMonth VARCHAR(20) 
    SET @firstOfMonth = CAST(@Year AS VARCHAR(4)) + '-' + CAST(@Month AS VARCHAR) + '-01' 

    declare @currDate DATETIME 
    set @currDate = CAST(@firstOfMonth as DATETIME) 

    declare @weekday INT 
    set @weekday = DATEPART(weekday, @currdate) 

    -- 7 = saturday, 1 = sunday 
    while @weekday = 1 OR @weekday = 7 
    begin 
     set @currDate = DATEADD(DAY, 1, @currDate) 
     set @weekday = DATEPART(weekday, @currdate) 
    end 

    return @currdate 
end 

私は「平日」の数字が固定されているかどうかを約100%わからないか、SQL Server上で、あなたのロケールに依存する場合があります。見てみな!

マルク・

1

我々は(擬似SQLで)のように、様々な「行方不明」の日付操作を可能にするもの、(年間数十のためのすべての日付と日付の部分で満たされている)我々のアプリケーションの日付のテーブルを持っている:

select min(ourdates.datevalue) 
from ourdates 
where ourdates.year=<given year> and ourdates.month=<given month> 
    and ourdates.isworkday 
    and not exists (
     select * from holidays 
     where holidays.datevalue=ourdates.datevalue 
    ) 
4

あなたは日が休日のテーブルではなく、日付が週末ではない月の最初の日のためになります:

select min(datePayment), datepart(mm, datePayment) 
from invoices 
where datepart(dw, datePayment) not in (1,7) --day of week 
and not exists (select holiday from holidays where holiday = datePayment) 
group by datepart(mm, datePayment) --monthnr 
+1

またはそれ以外の方法で1か月のすべての最初の作業日を事前に計算し、テーブルに格納します。あなたはこのテーブルをクエリするだけです – Scoregraphic

1

[OK]を、最初の刺しで、あなたの可能性次のコードをUDFに入れ、YearとMonthを変数として渡します。その後、月の最初の作業日であるTestDateを返すことができます。

DECLARE @Month INT 
DECLARE @Year INT 

SELECT @Month = 5 
SELECT @Year = 2009 

DECLARE @FirstDate DATETIME 
SELECT @FirstDate = CONVERT(varchar(4), @Year) + '-' + CONVERT(varchar(2), @Month) + '-' + '01 00:00:00.000' 

DROP TABLE #HOLIDAYS 
CREATE TABLE #HOLIDAYS (HOLIDAY DateTime) 

INSERT INTO #HOLIDAYS VALUES('2009-01-01 00:00:00.000') 
INSERT INTO #HOLIDAYS VALUES('2009-05-01 00:00:00.000') 

DECLARE @DateFound BIT 
SELECT @DateFound = 0 
WHILE(@DateFound = 0) 
BEGIN 
    IF(
     DATEPART(dw, @FirstDate) = 1 
     OR 
     DATEPART(dw, @FirstDate) = 1 
     OR 
     EXISTS(SELECT * FROM #HOLIDAYS WHERE HOLIDAY = @FirstDate) 
    ) 
    BEGIN 
     SET @FirstDate = DATEADD(dd, 1, @FirstDate) 
    END 
    ELSE 
    BEGIN 
     SET @DateFound = 1 
    END 
END 

SELECT @FirstDate 

あなたの休日の表には無限ループが含まれていますが、このソリューションでは気に入らないものもあります。 (あなたはループがまだ正しい月を見ていることを確認することができます)それは日付が等しいことに依存しています。例えば、すべて00:00:00です。最後に、文字列の連結を使用して1ヶ月前の1日を計算する方法が短期間でした。その月の実際の最初の日を見つけるもっと良い方法があります。

1

は、2009年の各月の営業日最初のNを取得します。アプリケーションは、これまで意志毎日のために1行:

select * from invoices as x 
where 
    datePayment between '2009-01-01' and '2009-12-31' 


    and exists 
    ( 
     select    
       1 
     from invoices 
     where 
      -- exclude holidays and sunday saturday... 
      (
       datepart(dw, datePayment) not in (1,7) -- day of week 


       /* 
       -- Postgresql and Oracle have programmer-friendly IN clause 
       and 
       (datepart(yyyy,datePayment), datepart(mm,datePayment)) 
       not in (select hyear, hday from holidays) 
       */ 


       -- this is the MSSQL equivalent of programmer-friendly IN 
       and 
       not exists 
       (
        select * from holidays 
        where 
         hyear = datepart(yyyy,datePayment) 
         and hmonth = datepart(mm, datePayment) 
       )         
      ) 
      -- ...exclude holidays and sunday saturday 



      -- get the month of x datePayment 
      and     
      (datepart(yyyy, datePayment) = datepart(yyyy, x.datePayment) 
      and datepart(mm, datePayment) = datepart(mm, x.datePayment)) 


     group by 
      datepart(yyyy, datePayment), datepart(mm, datePayment)  

     having 
      x.datePayment < MIN(datePayment) + @N -- up to N working days 
    ) 
2

よりむしろ日の休日テーブル除外するために、我々は、カレンダーのテーブルのアプローチを使用します必要(30年は控えめな11万行に及ぶ)。したがって、それはis_weekday列を持つだけでなく、それは企業に関連する他のものを持っています。 julianized_date。このように、すべての可能な日付はfirst_working_day_this_monthの準備ができた値を持ち、その場で毎回「計算」するのではなく、単純な検索(SQL製品は最適化される傾向にある)を伴います。

1

は、土曜日と日曜日は、5、6は現在の月の最初の月曜日

SELECT DATEADD(
    WEEK, 
    DATEDIFF(--x weeks between 1900-01-01 (Monday) and inner result 
     WEEK, 
     0, --1900-01-01 
     DATEADD(--inner result 
      DAY, 
      6 - DATEPART(DAY, GETDATE()), 
      GETDATE() 
     ) 
    ), 
    0 --1900-01-01 (Monday) 
) 
+0

これは答えではありませんが、とにかく良いヒントです。 –

0
SELECT DATEADD(day, DATEDIFF (day, 0, DATEADD (month, DATEDIFF (month, 0, GETDATE()), 0) -1)/7*7 + 7, 0); 
0
select if(weekday('yyyy-mm-01') < 5,'yyyy-mm-01',if(weekday('yyyy-mm-02') < 5,'yyyy-mm-02','yyyy-mm-03')) 

を返しますので、あなただけの最初の営業日

関連する問題