5

会社で毎月記念日を祝っているユーザーを検索するクエリを作成して、そのユーザーにメールを送信できるようにしようとしています (つまり、今日の日付が 3/27 の場合、1/27 にサインアップした人を検索します)。 、2/27、3/27、4/27など、年に関係なく)。

私の方法は、サインアップ日の「日」の部分が今日の日付の「日」の部分と等しいユーザーを見つけることです。

SELECT [User Id],[Sign Up Date] 
  FROM [Monthly Account Update] 
 WHERE DATEPART(DAY,[Sign Up Date]) = DAY(GETDATE())

ただし、もちろん、これは次のシナリオでは機能しません。

  1. 2 月の終わりには、毎月 29 日、30 日、31 日が記念日の人にメールを送る機会がありませんでした。理想的には、2 月 28 日に 29 日、30 日、31 日の人をまとめたいと思います。

  2. 日付が 30 日で終わる月に 1 か月おきに、31 日の日付の人にメールを送信できません。理想的には、日付が 30 と 31 の人をまとめたいと思います。

これらのことのいずれかを SQL クエリで達成できますか?

4

4 に答える 4

1

whereもっと複雑な句が必要です。力ずくの方法は次のとおりです。

SELECT [User Id],[Sign Up Date]
FROM [Monthly Account Update]
WHERE day([Sign Up Date]) = DAY(GETDATE()) or
      (month(getdate()) in (4, 6, 9, 11) and day(getdate()) = 30 and DAY([Sign Up Date]) = 31) or
      (month(getdate()) in (2) and day(getdate()) = 28 and DAY([Sign Up Date]) in (29, 30, 31))

2 月の場合は、28 日を探します。

于 2013-03-28T02:35:07.157 に答える
1

ここにいくつかの複雑な答えがあります!大幅に単純化できます。

create function dbo.fnIsMonthlyAnniversary(
    @startDate date,
    @comparisonDate date
)
returns bit
as
begin
    declare @retVal bit
    set @retVal = 0

    declare @deltaMonth int

    set @deltaMonth = datediff( mm, @startDate, @comparisonDate )

    if dateadd( mm, @deltaMonth, @startDate ) = @comparisonDate
    begin
        set @retVal = 1
    end

    return @retVal
end

-- usage:
select dbo.fnIsMonthlyAnniversary( '2012-12-31', CONVERT( date, getdate() ) )

あなたの使用法:

SELECT [User Id],[Sign Up Date] 
  FROM [Monthly Account Update] 
 WHERE 1 = dbo.fnIsMonthlyAnniversary( [Sign Up Date], CONVERT( date, getdate() ) )
于 2013-03-28T03:53:32.363 に答える
0

次のようなことを試してください:

1 から 1000 までの整数が入力された単一の列 [months] を持つ永続テーブル M を作成し、次のようなクエリを使用します。

SELECT [User Id],[Sign Up Date]
FROM [Monthly Account Update] AS U
JOIN M
ON CAST(getdate() AS DATE) = DATEADD(month,M.months,U.[Sign Up Date]

あまり効率的ではありませんが、少数の従業員の場合、1 日 1 回実行しても問題ありません。必要に応じて、M.months を SELECT リストに追加して、正確な記念日の月数を取得することもできます。

于 2013-03-28T03:00:34.157 に答える
0

1 か月を減算し、その月の追加が現在の日付を超えない最大 4 日間の範囲から、その後の各日を含めます。

DECLARE @Today DATE = '2/28/2013';
SELECT [Current] = @Today, [MonthAgo] = DATEADD(DAY,t.v,DATEADD(MONTH,-1,@Today))
FROM (VALUES(0),(1),(2),(3)) as t(v)
WHERE DATEADD(MONTH,1,DATEADD(DAY,t.v,DATEADD(MONTH,-1,@Today))) <= @Today;

2013 年 2 月 28 日の結果:

Current    MonthAgo
---------- ----------
2013-02-28 2013-01-28
2013-02-28 2013-01-29
2013-02-28 2013-01-30
2013-02-28 2013-01-31

2013 年 3 月 27 日の結果:

Current    MonthAgo
---------- ----------
2013-03-27 2013-02-27

2013 年 4 月 30 日の結果:

Current    MonthAgo
---------- ----------
2013-04-30 2013-03-30
2013-04-30 2013-03-31

...等。

編集:

上記の回答は、それを CTE にラップしてから、元のクエリに簡単な方法で結合することで適用できます。インライン関数呼び出しはクエリ全体で常に 4 行に制限されるため、日付関数のパフォーマンスへの影響は無視できることに注意してください。

DECLARE @Today DATE = GETDATE();

; WITH CTE AS (
    SELECT [Current] = @Today, [MonthAgo] = DATEADD(DAY,t.v,DATEADD(MONTH,-1,@Today))
    FROM (VALUES(0),(1),(2),(3)) as t(v)
    WHERE DATEADD(MONTH,1,DATEADD(DAY,t.v,DATEADD(MONTH,-1,@Today))) <= @Today
)
SELECT [User Id],[Sign Up Date] 
FROM [Monthly Account Update]
JOIN CTE ON CTE.[MonthAgo] = [Sign Up Date];
GO
于 2013-03-28T03:20:08.373 に答える