Câu trả lời này tuân theo định dạng T-SQL. Tôi khái niệm hóa vấn đề này là một trong khoảng cách tuyến tính giữa hai điểm ngày ở định dạng datetime, gọi chúng là Time1 và Time2; Time1 nên được căn chỉnh với giá trị 'cũ hơn' thời gian bạn đang xử lý (nói ngày sinh hoặc ngày tạo widget Ngày bắt đầu hành trình) và Time2 phải được căn chỉnh với giá trị 'mới hơn trong thời gian' (nói ngày chụp hoặc ngày hoàn thành tiện ích hoặc ngày đến điểm kiểm tra hành trình).
DECLARE @Time1 DATETIME
SET @Time1 = '12/14/2015'
DECLARE @Time2 DATETIME
SET @Time2 = '12/15/2016'
Giải pháp này sử dụng phép đo đơn giản, chuyển đổi và tính toán giao điểm nối tiếp của nhiều chu kỳ có độ dài khác nhau; ở đây: Thế kỷ, Thập kỷ, Năm, Tháng, Ngày (Cảm ơn Lịch của người Maya cho khái niệm này!). Lời cảm ơn nhanh chóng: Tôi cảm ơn những người đóng góp khác cho Stack Overflow cho tôi thấy một số chức năng thành phần trong quá trình này mà tôi đã ghép nối với nhau. Tôi đã đánh giá tích cực những điều này trong thời gian của tôi trên diễn đàn này.
Đầu tiên, xây dựng đường chân trời là tập hợp tuyến tính của các giao lộ của các chu kỳ Thế kỷ, Thập phân, Năm, Tháng, gia tăng theo tháng. Sử dụng chéo tham gia chức năng Descartes cho việc này. (Hãy suy nghĩ về điều này như tạo ra vải từ đó chúng ta sẽ cắt một chiều dài giữa các điểm hai 'yyyy-mm' để đo khoảng cách):
SELECT
Linear_YearMonths = (centuries.century + decades.decade + years.[year] + months.[Month]),
1 AS value
INTO #linear_months
FROM
(SELECT '18' [century] UNION ALL
SELECT '19' UNION ALL
SELECT '20') centuries
CROSS JOIN
(SELECT '0' [decade] UNION ALL
SELECT '1' UNION ALL
SELECT '2' UNION ALL
SELECT '3' UNION ALL
SELECT '4' UNION ALL
SELECT '5' UNION ALL
SELECT '6' UNION ALL
SELECT '7' UNION ALL
SELECT '8' UNION ALL
SELECT '9') decades
CROSS JOIN
(SELECT '1' [year] UNION ALL
SELECT '2' UNION ALL
SELECT '3' UNION ALL
SELECT '4' UNION ALL
SELECT '5' UNION ALL
SELECT '6' UNION ALL
SELECT '7' UNION ALL
SELECT '8' UNION ALL
SELECT '9' UNION ALL
SELECT '0') years
CROSS JOIN
(SELECT '-01' [month] UNION ALL
SELECT '-02' UNION ALL
SELECT '-03' UNION ALL
SELECT '-04' UNION ALL
SELECT '-05' UNION ALL
SELECT '-06' UNION ALL
SELECT '-07' UNION ALL
SELECT '-08' UNION ALL
SELECT '-09' UNION ALL
SELECT '-10' UNION ALL
SELECT '-11' UNION ALL
SELECT '-12') [months]
ORDER BY 1
Sau đó, chuyển đổi điểm ngày time1 và time2 của bạn vào 'yyyy -mm 'định dạng (Hãy suy nghĩ của những điểm này như là các điểm cắt tọa độ trên toàn bộ vải). Giữ lại bản gốc datetime phiên bản của các điểm cũng như:
SELECT
Time1 = @Time1,
[YYYY-MM of Time1] = CASE
WHEN LEFT(MONTH(@Time1),1) <> '1' OR MONTH(@Time1) = '1'
THEN (CAST(YEAR(@Time1) AS VARCHAR) + '-' + '0' + CAST(MONTH(@Time1) AS VARCHAR))
ELSE (CAST(YEAR(@Time1) AS VARCHAR) + '-' + CAST(MONTH(@Time1) AS VARCHAR))
END,
Time2 = @Time2,
[YYYY-MM of Time2] = CASE
WHEN LEFT(MONTH(@Time2),1) <> '1' OR MONTH(@Time2) = '1'
THEN (CAST(YEAR(@Time2) AS VARCHAR) + '-' + '0' + CAST(MONTH(@Time2) AS VARCHAR))
ELSE (CAST(YEAR(@Time2) AS VARCHAR) + '-' + CAST(MONTH(@Time2) AS VARCHAR))
END
INTO #datepoints
Sau đó, chọn khoảng cách thứ tự của các đơn vị 'yyyy-mm, ít một để chuyển đổi khoảng cách hồng y (tức là cắt một mảnh vải từ toàn bộ vải tại các điểm cắt được xác định và được đo thô của nó):
SELECT
d.*,
Months_Between = (SELECT (SUM(l.value) - 1) FROM #linear_months l
WHERE l.[Linear_YearMonths] BETWEEN d.[YYYY-MM of Time1] AND d.[YYYY-MM of Time2])
FROM #datepoints d
Raw Output: tôi gọi đây là một 'khoảng cách thô' vì thành phần tháng của 'yyyy-mm' hồng y khoảng cách có thể là một quá nhiều; các thành phần của chu kỳ ngày trong tháng cần được so sánh để xem liệu giá trị tháng trước có nên tính hay không. Trong ví dụ này, khoảng cách đầu ra thô là '12'. Nhưng điều này sai như 12/14 là trước ngày 12/15, do đó chỉ 11 tháng đã hết hiệu lực - chỉ một ngày rụt rè trong vòng 12 tháng. Do đó, chúng tôi phải đưa vào chu kỳ ngày trong tháng để có được câu trả lời cuối cùng. Chèn một so sánh vị trí 'tháng, ngày' giữa để xác định xem tháng ngày điểm mới nhất đếm trên danh nghĩa, hoặc không:
SELECT
d.*,
Months_Between = (SELECT (SUM(l.value) - 1) FROM AZ_VBP.[MY].[edg_Linear_YearMonths] l
WHERE l.[Linear_YearMonths] BETWEEN d.[YYYY-MM of Time1] AND d.[YYYY-MM of Time2])
+ (CASE WHEN DAY(Time1) < DAY(Time2)
THEN -1
ELSE 0
END)
FROM #datepoints d
Final Output: Câu trả lời đúng '11' bây giờ là đầu ra của chúng tôi. Và vì vậy, tôi hy vọng điều này sẽ giúp. Cảm ơn!
2009-01-31 đến 2009-02-28. Đó là 0 hay 1 tháng đầy đủ? –
số này phải là 0 – oscarkuo