ตามที่ระบุไว้ (หรืออย่างน้อยพูดพาดพิงถึง) ในคำตอบที่ยอดเยี่ยมจำนวนมากที่ได้รับแล้วปัญหานี้จะแก้ไขได้อย่างง่ายดายเมื่อคุณมีชุดของตัวเลขที่จะทำงานกับ
หมายเหตุ:ต่อไปนี้คือ T-SQL แต่เป็นเพียงการนำแนวคิดทั่วไปของฉันไปใช้ที่นี่และบนอินเทอร์เน็ตเป็นจำนวนมาก มันควรจะง่ายในการแปลงรหัสเป็นภาษาที่คุณเลือก
อย่างไร? พิจารณาคำถามนี้:
SELECT DATEADD(d, N, '0001-01-22')
FROM Numbers -- A table containing the numbers 0 through N
WHERE N <= 5;
ด้านบนสร้างช่วงวันที่ 1/22/0001 - 1/27/0001 และไม่สำคัญมาก มี 2 ชิ้นสำคัญของข้อมูลในแบบสอบถามดังกล่าวข้างต้นคือ: วันที่เริ่มต้นของ0001-01-22และชดเชย5ของ หากเรารวมข้อมูลสองชิ้นนี้เข้าด้วยกันเราก็จะมีวันที่สิ้นสุด ดังนั้นเมื่อได้รับสองวันการสร้างช่วงสามารถแบ่งได้ดังนี้:
- ค้นหาความแตกต่างระหว่างสองวันที่กำหนด (ชดเชย) ง่าย: - -- Returns 125 
SELECT ABS(DATEDIFF(d, '2014-08-22', '2014-12-25'))
 - ใช้- ABS()ที่นี่เพื่อให้แน่ใจว่าคำสั่งวันที่ไม่เกี่ยวข้อง
 
- สร้างชุดตัวเลขที่ จำกัด และทำได้ง่าย: - -- Returns the numbers 0-2
SELECT N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) - 1 
FROM(SELECT 'A' AS S UNION ALL SELECT 'A' UNION ALL SELECT 'A')
 - สังเกตว่าเราไม่สนใจสิ่งที่เราเลือก- FROMที่นี่ เราแค่ต้องตั้งค่าให้ทำงานด้วยเพื่อที่เราจะนับจำนวนแถวในนั้น ส่วนตัวผมใช้ TVF บางคนใช้ CTE ส่วนคนอื่นใช้ตารางตัวเลขแทนคุณจะได้ความคิด ฉันแนะนำให้ใช้วิธีที่มีประสิทธิภาพที่สุดที่คุณเข้าใจ
 
การรวมสองวิธีเหล่านี้จะช่วยแก้ปัญหาของเรา:
DECLARE @date1 DATE = '9001-11-21';
DECLARE @date2 DATE = '9001-11-23';
SELECT D = DATEADD(d, N, @date1)
FROM (
    SELECT N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) - 1
    FROM (SELECT 'A' AS S UNION ALL SELECT 'A' UNION ALL SELECT 'A') S
) Numbers
WHERE N <= ABS(DATEDIFF(d, @date1, @date2));
ตัวอย่างข้างต้นเป็นรหัสที่น่ากลัว แต่แสดงให้เห็นว่าทุกอย่างมารวมกันได้อย่างไร
สนุกมาก
ฉันต้องทำสิ่งนี้มากดังนั้นฉันจึงสรุปเหตุผลเป็นสอง TVF ตัวแรกสร้างช่วงของตัวเลขและตัวที่สองใช้ฟังก์ชันนี้เพื่อสร้างช่วงของวันที่ GenerateRangeSmallIntคณิตศาสตร์คือเพื่อให้แน่ใจเพื่อป้อนข้อมูลที่ไม่สำคัญและเพราะผมต้องการที่จะใช้อย่างเต็มรูปแบบของตัวเลขในใช้ได้
ฟังก์ชั่นต่อไปนี้ใช้เวลาประมาณ 16ms ของเวลา CPU เพื่อส่งคืนช่วงสูงสุดวันที่ 65536
CREATE FUNCTION dbo.GenerateRangeDate (   
    @date1 DATE,   
    @date2 DATE   
)   
RETURNS TABLE
WITH SCHEMABINDING   
AS   
RETURN (
    SELECT D = DATEADD(d, N + 32768, CASE WHEN @date1 <= @date2 THEN @date1 ELSE @date2 END)
    FROM dbo.GenerateRangeSmallInt(-32768, ABS(DATEDIFF(d, @date1, @date2)) - 32768)
);
GO
CREATE FUNCTION dbo.GenerateRangeSmallInt (
    @num1 SMALLINT = -32768
  , @num2 SMALLINT = 32767
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN (
    WITH Numbers(N) AS (
        SELECT N FROM(VALUES
            (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 16
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 32
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 48
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 64
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 80
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 96
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 112
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 128
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 144
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 160
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 176
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 192
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 208
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 224
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 240
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 256
        ) V (N)
    )
    SELECT TOP(ABS(CAST(@num1 AS INT) - CAST(@num2 AS INT)) + 1)
           N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + CASE WHEN @num1 <= @num2 THEN @num1 ELSE @num2 END - 1
    FROM Numbers A
       , Numbers B
);