我有兩個引數:
@startDate date = N'2022-01-17'
@endDate date = N'2022-02-28'
和一個有資料的表(與引數無關)
| 作業人員 | 開始日期 | 截止日期 |
|---|---|---|
| NR324 | 2022-01-09 | 2022-01-19 |
| NR326 | 2022-04-09 | 2022-05-13 |
任務是計算表日期之間每個月我的引數發生了多少天,并按引數的月份對它們進行分組((一月,二月))
輸出應該是這樣的:
| JobNr | Month | How many days |
|:-------|:----------:| --------------:|
| nr324 | January |3 |
| nr324 | February |0 |
| nr326 | January |0 |
| nr326 | February |0 |
** 3 是因為 17.01,18.01,19.01 處于 nr324 作業的選定期間,其他人為零,因為在選定期間 @startDate 日期 = N'2022-01-17' @endDate 日期 = N'2022-02-28'沒啥事兒。**
我無法完全理解它。我知道在某個地方應該有我認為時間差異和視窗函式。
uj5u.com熱心網友回復:
您在 CTE 月份走在正確的軌道上,但您需要注意結束條件,例如 2022-01-31 到 2022-02-01 的范圍。從那里您可以CROSS JOIN使用帶有作業資料的日歷來計算作業、月份和總體范圍之間的重疊日期數。
SQL Server 沒有 LEAST() 或 GREATEST() 函式來對離散值進行操作,因此需要另一種方法,對于兩個值,可以使用簡單的 CASE 陳述句,但對于比較 3 個或更多值,該邏輯得到越來越復雜。保持事情相對簡單的一個技巧是使用 MIN() 和 MAX() 聚合函式對使用 VALUES 語法定義的一組資料進行操作。
從那里,您可以計算天數,小心避免負范圍。
最終結果是這樣的:
;WITH Months (Date) AS (
SELECT DATEADD(DAY, 1 - DAY(@startdate), @startdate) -- First-of-month
UNION ALL
SELECT DATEADD(month, 1, Date)
from months
where DATEADD(month, 1, Date) <= @enddate -- Inclusive
)
SELECT
JobNr = D.jobnr,
Month = DATENAME(month, M.Date),
[How Many Days] = CASE
WHEN R.RangeStart <= R.RangeEnd
THEN 1 DATEDIFF(DAY, R.RangeStart, R.RangeEnd)
ELSE 0
END
FROM Months M
CROSS JOIN @Data D
OUTER APPLY(
SELECT RangeStart = MAX(StartDate), RangeEnd = MIN(EndDate)
FROM (
VALUES
(@startDate, @endDate),
(M.Date, EOMONTH(m.Date)),
(D.startdate, D.duedate)
) A(StartDate, EndDate)
) R
ORDER BY D.jobnr, M.Date
假定結束日期(@endDate 和到期日期)都包含在內。上述邏輯也適用于跨越多年的范圍,您可能希望添加YEAR(M.Date)到結果中。
請參閱此 db<>fiddle進行演示。
uj5u.com熱心網友回復:
declare @a table (
jobnr VARCHAR(6) NOT NULL
,startdate DATE NOT NULL
,duedate DATE NOT NULL
);
INSERT INTO @a(jobnr,startdate,duedate) VALUES
('nr324','2022-01-09','2022-01-19'),
('nr326','2022-04-09','2022-05-13');
使用joinandunion和format如下
DECLARE @startDate DATE = N'2022-01-17' --yourvariable
DECLARE @endDate DATE = N'2022-02-28' -- yourvariable
SELECT a.month1,
Count(b.month1) AS 'How many days'
FROM (SELECT Format(@startDate, 'MMMM') month1---month as name
UNION
SELECT Format(@endDate, 'MMMM') month1) a
LEFT JOIN (SELECT jobnr,
startdate,
Format(startdate, 'MMMM') month1
FROM @a --your table
UNION
SELECT jobnr,
duedate,
Format(duedate, 'MMMM') month1
FROM @a) b
ON a.month1 = b.month1
GROUP BY b.month1,
a.month1
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/447371.html
