SQL Server 代理 - 在每个月末使用日期变量运行查询

Tha*_*nos 3 sql-server sql-server-2008-r2 sql-server-agent

我正在运行 SQL Server 2008 R2,我需要创建一个新作业,该作业基本上会在每个月初(每个月 1 日上午 01:00)运行查询。

这是查询:

INSERT INTO [SupportTracker].[dbo].[DashboardRecords]
SELECT [bg_id]
      ,[bg_short_desc]
      ,[bg_reported_date]
      ,[bg_status_updated_date]
      ,[us_firstname]
      ,[us_lastname]
      ,[LastUpdatedUserFirstname]
      ,[LastUpdatedUserLastname]
      ,[st_name]
      ,[pr_name]
      ,[ct_name]
      ,[pj_name]
      ,[AssignedUserFirstname]
      ,[AssignedUserLastname]
      ,[bg_project]
      ,[no_of_hours]
      ,[BugType]
      ,[SubType]
      ,[Device]
      ,[pj_parent_id]
FROM [SupportTracker].[dbo].[ViewIssueListwBugTypeNDevice]
WHERE 
     bg_reported_date between '2012-12-01 00:00:00.000' AND '2012-12-31 23:59:59.999' 
     AND bg_id NOT IN (SELECT bg_id FROM [SupportTracker].[dbo].[DashboardRecords])
ORDER BY bg_reported_date ASC
Run Code Online (Sandbox Code Playgroud)

我的问题是在WHERE条款上。这两个日期每个月都必须更改。

  • 如果我们在01-01-2013 01:00:00:00,我需要这两个日期:
    2012-12-01 00:00:00.0002012-12-31 23:59:59.999

  • 如果我们在01-02-2013 01:00:00:00,我需要这两个日期是:
    2013-01-01 00:00:00.0002013-01-31 23:59:59.999

基本上我需要捕获数据库的一部分并将其保存在表中,就像每个月末一样......

谢谢

swa*_*eck 7

要查找该月的第一天和最后一天:

DECLARE @MonthStart DATETIME
DECLARE @Date  DATETIME
DECLARE @next DATETIME 
-- create the required date. because today is the 21st i subtracted month. 
-- since you're running the job on the first day of the new month, 
-- you may want to change MONTH to DAY. however, if the job fails that change
-- that may cause you some problems
SET @Date = DATEADD(MONTH,-1,DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) 

-- get the first day of the month of the date specified
SET @MonthStart = DATEADD(DAY, 1, @Date - DAY(@Date) + 1) -1

-- get the first day of next month
SET @Next = DATEADD(MONTH,1,@MonthStart)

-- prove to yourself that these dates are correct (sanity check)
SELECT @MonthStart, @next
Run Code Online (Sandbox Code Playgroud)

我已经为您安排了这样的内容,以便您可以遵循逻辑,可以根据需要进行编辑。

NOT IN顺便说一句,该约定在某种程度上是一种反模式,一些专家建议不要使用BETWEEN.

左加入

INSERT INTO [SupportTracker].[dbo].[DashboardRecords]
SELECT [bg_id]
      ,[bg_short_desc]
      ,[bg_reported_date]
      ,[bg_status_updated_date]
      ,[us_firstname]
      ,[us_lastname]
      ,[LastUpdatedUserFirstname]
      ,[LastUpdatedUserLastname]
      ,[st_name]
      ,[pr_name]
      ,[ct_name]
      ,[pj_name]
      ,[AssignedUserFirstname]
      ,[AssignedUserLastname]
      ,[bg_project]
      ,[no_of_hours]
      ,[BugType]
      ,[SubType]
      ,[Device]
      ,[pj_parent_id]
FROM [SupportTracker].[dbo].[ViewIssueListwBugTypeNDevice] b
LEFT JOIN [SupportTracker].[dbo].[DashboardRecords] d
    ON b.bg_id = d.bg_id
WHERE b.bg_reported_date >= @MonthStart and b.bg_reported_date < @Next
    AND d.[bg_short_desc] IS NULL
Run Code Online (Sandbox Code Playgroud)

(这假设 [bg_short_desc] 是[DashboardRecords]表中不可为空的字段。

更好的是

不存在

INSERT INTO [SupportTracker].[dbo].[DashboardRecords]

SELECT [bg_id]
      ,[bg_short_desc]
      ,[bg_reported_date]
      ,[bg_status_updated_date]
      ,[us_firstname]
      ,[us_lastname]
      ,[LastUpdatedUserFirstname]
      ,[LastUpdatedUserLastname]
      ,[st_name]
      ,[pr_name]
      ,[ct_name]
      ,[pj_name]
      ,[AssignedUserFirstname]
      ,[AssignedUserLastname]
      ,[bg_project]
      ,[no_of_hours]
      ,[BugType]
      ,[SubType]
      ,[Device]
      ,[pj_parent_id]
FROM [SupportTracker].[dbo].[ViewIssueListwBugTypeNDevice] b
WHERE b.bg_reported_date >= @MonthStart and b.bg_reported_date < @Next
    AND NOT EXISTS (SELECT 1 FROM [SupportTracker].[dbo].[DashboardRecords] d
        WHERE b.bg_id = d.bg_id);
Run Code Online (Sandbox Code Playgroud)

另外,你为什么要订购你的插件?当您从DashboardRecords表格中进行选择时,订购会更有用,对吗?


Aar*_*and 7

BETWEEN由于我在这篇博文中概述的原因,您不想使用它来满足此查询:

相反,您需要一个开放式日期范围。从相关月份的第一天开始,并且小于下个月。要确定给定任何日期的月份的第一天,您可以执行以下操作:

SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0);
Run Code Online (Sandbox Code Playgroud)

要获得下个月的第一个,只需添加一个:

SELECT DATEADD(MONTH, 1+DATEDIFF(MONTH, 0, GETDATE()), 0);
Run Code Online (Sandbox Code Playgroud)

当然,如果你只希望上个月在当月的第一天,而这个月在第一天之后,那么你可以说:

SELECT DATEADD(MONTH, 1+DATEDIFF(MONTH, 0, DATEADD(DAY, -1, GETDATE())), 0);
Run Code Online (Sandbox Code Playgroud)

因此,对于您的查询,如果您始终希望它相对于当前月份:

...
FROM SupportTracker.dbo.ViewIssueListwBugTypeNDevice AS v
WHERE NOT EXISTS 
(
  SELECT 1 FROM SupportTracker.dbo.DashboardRecords
    WHERE bg_id = v.bg_id
)
AND v.bg_reported_date >= DATEADD(MONTH, 0, DATEDIFF(MONTH, 0, DATEADD(DAY, -1, GETDATE()))
AND v.bg_reported_date < DATEADD(MONTH, 1, DATEDIFF(MONTH, 0, DATEADD(DAY, -1, GETDATE()));
Run Code Online (Sandbox Code Playgroud)

或者如果你想把日期作为可选参数,你不需要减去一天,只需传入你真正想要的月份内的任何日期(如果你传入NULL,它仍然会回落到上面的公式):

  @Month DATE = NULL
...

  SET @Month = DATEADD(MONTH, 0, DATEDIFF(MONTH, 0, COALESCE(@Month, 
    DATEADD(DAY, -1, GETDATE())));  

...
FROM SupportTracker.dbo.ViewIssueListwBugTypeNDevice AS v
WHERE NOT EXISTS 
(
  SELECT 1 FROM SupportTracker.dbo.DashboardRecords
    WHERE bg_id = v.bg_id
)
AND v.bg_reported_date >= @Month
AND v.bg_reported_date < DATEADD(MONTH, 1, @Month);
Run Code Online (Sandbox Code Playgroud)

但是,一般来说,以下内容更好地确定给定月份,因为datediff可能会导致问题

SELECT FirstOfThisMonth = DATEADD(DAY, 1-DAY(GETDATE()), CONVERT(date, GETDATE()));
Run Code Online (Sandbox Code Playgroud)