我需要帮助来计算ssis中两个日期之间的工作日。
来源是excel,目的地是oracle。
示例日期:我有两个来自excel源的日期字段,有时候date1将大于date2日期。
ID | DATE1 | DATE2
------------------------------
1 | 22-MAR-2017 | 28-MAR-2017
2 | 13-SEP-2017 | 01-SEP-2017
3 | 11-SEP-2017 | 4-SEP-2017
我尝试在派生列中使用类似的表达式......但它没有用。
(DATEDIFF(dd, @StartDate, @EndDate) + 1) -(DATEDIFF(wk, @StartDate, @EndDate) * 2)
答案 0 :(得分:0)
这通常通过设置具有各种属性的日期维度在数据库中完成。
Date Month Year FiscalYear FiscalMonth .... BusinessDay
3/22/17 March 2017 2017 3 1
3/23/17
...
Select BusDays = (Select SUM(BusinessDay) from DimDate between @startdate and @enddate)
我通常会为表示层保留此计算,而不使用SSIS。并创建一个函数来传递开始和结束日期。
答案 1 :(得分:0)
首先,您可以在派生列中执行此操作,但是您在查找工作日时会遇到问题,而且当您使用date1>时会出现问题。 DATE2。
因此,我会将EXCEL数据提取到表中,然后根据该源表创建逻辑。就像我的例子:
首先创建一个日历表:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET NOCOUNT ON
SET ANSI_WARNINGS OFF
SET ARITHABORT OFF
SET ARITHIGNORE ON
SET TEXTSIZE 2147483647
-----------------------------------------------------------------------------------------------------------------------------
-- Script Details: Listing Of Standard Details Related To The Script
-----------------------------------------------------------------------------------------------------------------------------
-- Purpose: Date Calendar Cross-Reference Table
-- Create Date (MM/DD/YYYY): 10/29/2009
-- Developer: Sean Smith (s.smith.sql AT gmail DOT com)
-- Additional Notes: N/A
-----------------------------------------------------------------------------------------------------------------------------
-- Modification History: Listing Of All Modifications Since Original Implementation
-----------------------------------------------------------------------------------------------------------------------------
-- Description: Fixed Bug Affecting "month_weekdays_remaining" And "quarter_weekdays_remaining" Columns
-- Date (MM/DD/YYYY): 07/02/2014
-- Developer: Sean Smith (s.smith.sql AT gmail DOT com)
-- Additional Notes: N/A
-----------------------------------------------------------------------------------------------------------------------------
-- Declarations / Sets: Declare And Set Variables
-----------------------------------------------------------------------------------------------------------------------------
DECLARE
@Date_Start AS DATETIME
,@Date_End AS DATETIME
SET @Date_Start = '20000101'
SET @Date_End = '20301231'
-----------------------------------------------------------------------------------------------------------------------------
-- Error Trapping: Check If Permanent Table(s) Already Exist(s) And Drop If Applicable
-----------------------------------------------------------------------------------------------------------------------------
IF OBJECT_ID (N'dbo.date_calendar', N'U') IS NOT NULL
BEGIN
DROP TABLE dbo.date_calendar
END
-----------------------------------------------------------------------------------------------------------------------------
-- Permanent Table: Create Date Xref Table
-----------------------------------------------------------------------------------------------------------------------------
CREATE TABLE dbo.date_calendar
(
calendar_date DATETIME NOT NULL CONSTRAINT PK_date_calendar_calendar_date PRIMARY KEY CLUSTERED
,calendar_year SMALLINT
,calendar_month TINYINT
,calendar_day TINYINT
,calendar_quarter TINYINT
,first_day_in_week DATETIME
,last_day_in_week DATETIME
,is_week_in_same_month INT
,first_day_in_month DATETIME
,last_day_in_month DATETIME
,is_last_day_in_month INT
,first_day_in_quarter DATETIME
,last_day_in_quarter DATETIME
,is_last_day_in_quarter INT
,day_of_week TINYINT
,week_of_month TINYINT
,week_of_quarter TINYINT
,week_of_year TINYINT
,days_in_month TINYINT
,month_days_remaining TINYINT
,weekdays_in_month TINYINT
,month_weekdays_remaining TINYINT
,month_weekdays_completed TINYINT
,days_in_quarter TINYINT
,quarter_days_remaining TINYINT
,quarter_days_completed TINYINT
,weekdays_in_quarter TINYINT
,quarter_weekdays_remaining TINYINT
,quarter_weekdays_completed TINYINT
,day_of_year SMALLINT
,year_days_remaining SMALLINT
,is_weekday INT
,is_leap_year INT
,day_name VARCHAR (10)
,month_day_name_instance TINYINT
,quarter_day_name_instance TINYINT
,year_day_name_instance TINYINT
,month_name VARCHAR (10)
,year_week CHAR (6)
,year_month CHAR (6)
,year_quarter CHAR (6)
)
-----------------------------------------------------------------------------------------------------------------------------
-- Table Insert: Populate Base Date Values Into Permanent Table Using Common Table Expression (CTE)
-----------------------------------------------------------------------------------------------------------------------------
;WITH CTE_Date_Base_Table AS
(
SELECT
@Date_Start AS calendar_date
UNION ALL
SELECT
DATEADD (DAY, 1, DBT.calendar_date)
FROM
CTE_Date_Base_Table DBT
WHERE
DATEADD (DAY, 1, DBT.calendar_date) <= @Date_End
)
INSERT INTO dbo.date_calendar
(
calendar_date
)
SELECT
DBT.calendar_date
FROM
CTE_Date_Base_Table DBT
OPTION
(MAXRECURSION 0)
-----------------------------------------------------------------------------------------------------------------------------
-- Table Update I: Populate Additional Date Xref Table Fields (Pass I)
-----------------------------------------------------------------------------------------------------------------------------
UPDATE
dbo.date_calendar
SET
calendar_year = DATEPART (YEAR, calendar_date)
,calendar_month = DATEPART (MONTH, calendar_date)
,calendar_day = DATEPART (DAY, calendar_date)
,calendar_quarter = DATEPART (QUARTER, calendar_date)
,first_day_in_week = DATEADD (DAY, -DATEPART (WEEKDAY, calendar_date) + 1, calendar_date)
,first_day_in_month = CONVERT (VARCHAR (6), calendar_date, 112) + '01'
,day_of_week = DATEPART (WEEKDAY, calendar_date)
,week_of_year = DATEPART (WEEK, calendar_date)
,day_of_year = DATEPART (DAYOFYEAR, calendar_date)
,is_weekday = ISNULL ((CASE
WHEN ((@@DATEFIRST - 1) + (DATEPART (WEEKDAY, calendar_date) - 1)) % 7 NOT IN (5, 6) THEN 1
END), 0)
,day_name = DATENAME (WEEKDAY, calendar_date)
,month_name = DATENAME (MONTH, calendar_date)
ALTER TABLE dbo.date_calendar ALTER COLUMN calendar_year INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN calendar_month INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN calendar_day INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN calendar_quarter INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN first_day_in_week DATETIME NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN first_day_in_month DATETIME NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN day_of_week INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN week_of_year INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN day_of_year INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN is_weekday INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN day_name VARCHAR (10) NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN month_name VARCHAR (10) NOT NULL
CREATE NONCLUSTERED INDEX IX_date_calendar_calendar_year ON dbo.date_calendar (calendar_year)
CREATE NONCLUSTERED INDEX IX_date_calendar_calendar_month ON dbo.date_calendar (calendar_month)
CREATE NONCLUSTERED INDEX IX_date_calendar_calendar_quarter ON dbo.date_calendar (calendar_quarter)
CREATE NONCLUSTERED INDEX IX_date_calendar_first_day_in_week ON dbo.date_calendar (first_day_in_week)
CREATE NONCLUSTERED INDEX IX_date_calendar_day_of_week ON dbo.date_calendar (day_of_week)
CREATE NONCLUSTERED INDEX IX_date_calendar_is_weekday ON dbo.date_calendar (is_weekday)
-----------------------------------------------------------------------------------------------------------------------------
-- Table Update II: Populate Additional Date Xref Table Fields (Pass II)
-----------------------------------------------------------------------------------------------------------------------------
UPDATE
dbo.date_calendar
SET
last_day_in_week = first_day_in_week + 6
,last_day_in_month = DATEADD (MONTH, 1, first_day_in_month) - 1
,first_day_in_quarter = A.first_day_in_quarter
,last_day_in_quarter = A.last_day_in_quarter
,week_of_month = DATEDIFF (WEEK, first_day_in_month, calendar_date) + 1
,week_of_quarter = (week_of_year - A.min_week_of_year_in_quarter) + 1
,is_leap_year = ISNULL ((CASE
WHEN calendar_year % 400 = 0 THEN 1
WHEN calendar_year % 100 = 0 THEN 0
WHEN calendar_year % 4 = 0 THEN 1
END),0)
,year_week = CONVERT (VARCHAR (4), calendar_year) + RIGHT ('0' + CONVERT (VARCHAR (2), week_of_year), 2)
,year_month = CONVERT (VARCHAR (4), calendar_year) + RIGHT ('0' + CONVERT (VARCHAR (2), calendar_month), 2)
,year_quarter = CONVERT (VARCHAR (4), calendar_year) + 'Q' + CONVERT (VARCHAR (1), calendar_quarter)
FROM
(
SELECT
X.calendar_year AS subquery_calendar_year
,X.calendar_quarter AS subquery_calendar_quarter
,MIN (X.calendar_date) AS first_day_in_quarter
,MAX (X.calendar_date) AS last_day_in_quarter
,MIN (X.week_of_year) AS min_week_of_year_in_quarter
FROM
dbo.date_calendar X
GROUP BY
X.calendar_year
,X.calendar_quarter
) A
WHERE
A.subquery_calendar_year = calendar_year
AND A.subquery_calendar_quarter = calendar_quarter
ALTER TABLE dbo.date_calendar ALTER COLUMN last_day_in_week DATETIME NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN last_day_in_month DATETIME NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN first_day_in_quarter DATETIME NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN last_day_in_quarter DATETIME NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN week_of_month INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN week_of_quarter INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN is_leap_year INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN year_week VARCHAR (6) NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN year_month VARCHAR (6) NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN year_quarter VARCHAR (6) NOT NULL
CREATE NONCLUSTERED INDEX IX_date_calendar_last_day_in_week ON dbo.date_calendar (last_day_in_week)
CREATE NONCLUSTERED INDEX IX_date_calendar_year_month ON dbo.date_calendar (year_month)
CREATE NONCLUSTERED INDEX IX_date_calendar_year_quarter ON dbo.date_calendar (year_quarter)
-----------------------------------------------------------------------------------------------------------------------------
-- Table Update III: Populate Additional Date Xref Table Fields (Pass III)
-----------------------------------------------------------------------------------------------------------------------------
UPDATE
dbo.date_calendar
SET
is_last_day_in_month = (CASE
WHEN last_day_in_month = calendar_date THEN 1
ELSE 0
END)
,is_last_day_in_quarter = (CASE
WHEN last_day_in_quarter = calendar_date THEN 1
ELSE 0
END)
,days_in_month = DATEPART (DAY, last_day_in_month)
,weekdays_in_month = A.weekdays_in_month
,days_in_quarter = DATEDIFF (DAY, first_day_in_quarter, last_day_in_quarter) + 1
,quarter_days_remaining = DATEDIFF (DAY, calendar_date, last_day_in_quarter)
,weekdays_in_quarter = B.weekdays_in_quarter
,year_days_remaining = (365 + is_leap_year) - day_of_year
FROM
(
SELECT
X.year_month AS subquery_year_month
,SUM (X.is_weekday) AS weekdays_in_month
FROM
dbo.date_calendar X
GROUP BY
X.year_month
) A
,(
SELECT
X.year_quarter AS subquery_year_quarter
,SUM (X.is_weekday) AS weekdays_in_quarter
FROM
dbo.date_calendar X
GROUP BY
X.year_quarter
) B
WHERE
A.subquery_year_month = year_month
AND B.subquery_year_quarter = year_quarter
ALTER TABLE dbo.date_calendar ALTER COLUMN is_last_day_in_month INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN is_last_day_in_quarter INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN days_in_month INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN weekdays_in_month INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN days_in_quarter INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN quarter_days_remaining INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN weekdays_in_quarter INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN year_days_remaining INT NOT NULL
-----------------------------------------------------------------------------------------------------------------------------
-- Table Update IV: Populate Additional Date Xref Table Fields (Pass IV)
-----------------------------------------------------------------------------------------------------------------------------
UPDATE
dbo.date_calendar
SET
month_weekdays_remaining = weekdays_in_month - A.month_weekdays_remaining_subtraction
,quarter_weekdays_remaining = weekdays_in_quarter - A.quarter_weekdays_remaining_subtraction
FROM
(
SELECT
X.calendar_date AS subquery_calendar_date
,ROW_NUMBER () OVER
(
PARTITION BY
X.year_month
ORDER BY
X.calendar_date
) AS month_weekdays_remaining_subtraction
,ROW_NUMBER () OVER
(
PARTITION BY
X.year_quarter
ORDER BY
X.calendar_date
) AS quarter_weekdays_remaining_subtraction
FROM
dbo.date_calendar X
WHERE
X.is_weekday = 1
) A
WHERE
A.subquery_calendar_date = calendar_date
-----------------------------------------------------------------------------------------------------------------------------
-- Table Update V: Populate Additional Date Xref Table Fields (Pass V)
-----------------------------------------------------------------------------------------------------------------------------
UPDATE
X
SET
X.month_weekdays_remaining = (CASE
WHEN Y.calendar_month = X.calendar_month AND Y.month_weekdays_remaining IS NOT NULL THEN Y.month_weekdays_remaining
WHEN Z.calendar_month = X.calendar_month AND Z.month_weekdays_remaining IS NOT NULL THEN Z.month_weekdays_remaining
ELSE X.weekdays_in_month
END)
,X.quarter_weekdays_remaining = (CASE
WHEN Y.calendar_quarter = X.calendar_quarter AND Y.quarter_weekdays_remaining IS NOT NULL THEN Y.quarter_weekdays_remaining
WHEN Z.calendar_quarter = X.calendar_quarter AND Z.quarter_weekdays_remaining IS NOT NULL THEN Z.quarter_weekdays_remaining
ELSE X.weekdays_in_quarter
END)
FROM
dbo.date_calendar X
LEFT JOIN dbo.date_calendar Y ON DATEADD (DAY, 1, Y.calendar_date) = X.calendar_date
LEFT JOIN dbo.date_calendar Z ON DATEADD (DAY, 2, Z.calendar_date) = X.calendar_date
WHERE
X.month_weekdays_remaining IS NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN month_weekdays_remaining INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN quarter_weekdays_remaining INT NOT NULL
-----------------------------------------------------------------------------------------------------------------------------
-- Table Update VI: Populate Additional Date Xref Table Fields (Pass VI)
-----------------------------------------------------------------------------------------------------------------------------
UPDATE
dbo.date_calendar
SET
is_week_in_same_month = A.is_week_in_same_month
,month_days_remaining = days_in_month - calendar_day
,month_weekdays_completed = weekdays_in_month - month_weekdays_remaining
,quarter_days_completed = days_in_quarter - quarter_days_remaining
,quarter_weekdays_completed = weekdays_in_quarter - quarter_weekdays_remaining
,month_day_name_instance = A.month_day_name_instance
,quarter_day_name_instance = A.quarter_day_name_instance
,year_day_name_instance = A.year_day_name_instance
FROM
(
SELECT
X.calendar_date AS subquery_calendar_date
,ISNULL ((CASE
WHEN DATEDIFF (MONTH, X.first_day_in_week, X.last_day_in_week) = 0 THEN 1
END), 0) AS is_week_in_same_month
,ROW_NUMBER () OVER
(
PARTITION BY
X.year_month
,X.day_name
ORDER BY
X.calendar_date
) AS month_day_name_instance
,ROW_NUMBER () OVER
(
PARTITION BY
X.year_quarter
,X.day_name
ORDER BY
X.calendar_date
) AS quarter_day_name_instance
,ROW_NUMBER () OVER
(
PARTITION BY
X.calendar_year
,X.day_name
ORDER BY
X.calendar_date
) AS year_day_name_instance
FROM
dbo.date_calendar X
) A
WHERE
A.subquery_calendar_date = calendar_date
ALTER TABLE dbo.date_calendar ALTER COLUMN is_week_in_same_month INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN month_days_remaining INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN month_weekdays_completed INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN quarter_days_completed INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN quarter_weekdays_completed INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN month_day_name_instance INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN quarter_day_name_instance INT NOT NULL
ALTER TABLE dbo.date_calendar ALTER COLUMN year_day_name_instance INT NOT NULL
-----------------------------------------------------------------------------------------------------------------------------
-- Main Query: Final Display / Output
-----------------------------------------------------------------------------------------------------------------------------
SELECT
URD.*
FROM
dbo.date_calendar URD
ORDER BY
URD.calendar_date
然后,您现在可以使用您的值加入日历表:
DECLARE @MyTable TABLE
(Date1 date,
Date2 date
)
INSERT INTO @MyTable (Date1,Date2)
VALUES
( '2017-03-22','2017-03-28'),
( '2017-09-13','2017-09-01'),
( '2017-09-11','2017-09-14')
select sum(Is_weekday) as WorkingDays,Date1,Date2 from (
Select Is_weekday, Date1,Date2 from (
select
case when Date1 > Date2 then Date2 else Date1 end as Date1,Case when Date1> Date2 then Date1 else Date2 end as Date2 from (
Select * from @MyTable
) x
) z
left join dbo.date_calendar b on cast(b.calendar_date as date) between z.Date1 and z.Date2
where is_weekday = 1
) y group by Date1,Date2
<强>结果:强>