我目前正在制定一项要求,找出失踪期,然后确定它是否在失踪期之前是连续的
以下是我的示例表结构。
第一步:在以下示例表中查看最近6个月(2014 7 - 2014 12
)。它错过了两个月8& 11.以第一个实例8开始。
第二步:从失去第一个实例开始的6个月后返回 - (2014 2- 2014 7
) - 看看他们是否在任何月份失踪。如果否(一切都是连续的) - 如果是,则选择/包括此记录(缺少几个月) - 不要选择此记录。
Year Month
2014 1
2014 2
2014 3
2014 4
2014 5
2014 6
2014 7
2014 9
2014 10
2014 12
我可以选择最后6条记录并按行号分区,看看它是否缺少任何记录。但我不知道如何找到连续的,也选择缺失的时期。
我正在尝试在Transact-SQL中进行尽可能多的过滤,以便我可以专注于c#上的其他验证。
我创建的查询是为了找到第一个缺失的期间(未完成)
SELECT f.TYEAR,f.TMONTH, f.TMONTH+1 AS MISSING FROM #TEMPTABLE AS F
LEFT OUTER JOIN #TEMPTABLE AS F2 ON f.TMONTH+1 = f2.TMONTH
WHERE f2.TAXPERIOD IS NULL
注意:上面的例子可以跨越两个日历年的b / w。 2013 mm - 2014 mm
答案 0 :(得分:0)
我认为下面的代码应该可行,但我还没有正确测试它。但是你会得到这个想法 -
DECLARE @TmpBaseTable TABLE ([Year] SMALLINT, [Month] TINYINT)
DECLARE @TmpSixMonthTable TABLE (TmpYear SMALLINT, TmpMonth TINYINT)
DECLARE @TmpDate DATE
DECLARE @MissingYear SMALLINT
DECLARE @MissingMonth TINYINT
DECLARE @TmpCount TINYINT
INSERT INTO @TmpBaseTable ([Year], [Month])
SELECT 2014, 1 UNION ALL
SELECT 2014, 2 UNION ALL
SELECT 2014, 3 UNION ALL
SELECT 2014, 4 UNION ALL
SELECT 2014, 5 UNION ALL
SELECT 2014, 6 UNION ALL
SELECT 2014, 7 UNION ALL
SELECT 2014, 8 UNION ALL
SELECT 2014, 9 UNION ALL
SELECT 2014, 10 UNION ALL
SELECT 2014, 11 UNION ALL
SELECT 2014, 12 UNION ALL
SELECT 2015, 1 UNION ALL
SELECT 2015, 3 UNION ALL
SELECT 2015, 4
SELECT TOP 1 @TmpDate = CAST(CAST(tmpYear AS VARCHAR) + '-' + CAST(tmpMonth AS VARCHAR) + '-' + CAST(1 AS VARCHAR) AS DATE)
FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY [Year], [Month]) AS RowID, [Month] AS tmpMonth, [Year] AS tmpYear
FROM @TmpBaseTable
)
tmp ORDER BY RowID DESC
INSERT INTO @TmpSixMonthTable (TmpMonth, TmpYear)
SELECT DATEPART(MONTH, DATEADD (MONTH, -5, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -5, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -4, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -4, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -3, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -3, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -2, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -2, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -1, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -1, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -0, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -0, @TmpDate))
SELECT TOP 1 @MissingMonth = tmpSix.TmpMonth, @MissingYear = tmpSix.TmpYear FROM @TmpSixMonthTable tmpSix
LEFT OUTER JOIN @TmpBaseTable tmpBase ON tmpSix.TmpMonth = tmpBase.[Month] AND tmpSix.TmpYear = tmpBase.[Year]
WHERE tmpBase.[Year] IS NULL
SET @TmpDate = CAST(CAST(@MissingYear AS VARCHAR) + '-' + CAST(@MissingMonth AS VARCHAR) + '-' + CAST(1 AS VARCHAR) AS DATE)
DELETE FROM @TmpSixMonthTable
INSERT INTO @TmpSixMonthTable (TmpMonth, TmpYear)
SELECT DATEPART(MONTH, DATEADD (MONTH, -6, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -6, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -5, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -5, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -4, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -4, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -3, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -3, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -2, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -2, @TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -1, @TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -1, @TmpDate))
SELECT @TmpCount = COUNT(1) FROM @TmpSixMonthTable tmp1
INNER JOIN @TmpBaseTable tmp2 ON tmp1.TmpMonth = tmp2.[Month] AND tmp1.TmpYear = tmp2.[Year]
IF(@TmpCount = 6)
BEGIN
SELECT tmp2.[Month], tmp2.[Year] FROM @TmpSixMonthTable tmp1
INNER JOIN @TmpBaseTable tmp2 ON tmp1.TmpMonth = tmp2.[Month] AND tmp1.TmpYear = tmp2.[Year]
END
可以采用比这更聪明的方式:)
答案 1 :(得分:0)
这个已经过测试,我花了一些时间在它上面,请告诉我如果你对结果感到满意并投票如果是,欢呼:-) PS:表dbo.Months_and_Years包含你的数据(缺少2个月)
CREATE TABLE dbo.Test_Table (
[Year] SMALLINT,
[Month] TINYINT
);
INSERT INTO dbo.Test_Table
VALUES
(2014, 1),
(2014, 2),
(2014, 3),
(2014, 4),
(2014, 5),
(2014, 6),
(2014, 7),
(2014, 9),
(2014, 10),
(2014, 12);
DECLARE @MinValue TINYINT = 1
DECLARE @MaxValue TINYINT = 100
WHILE @MinValue < = @MaxValue
BEGIN
DECLARE @Missing_Month TINYINT = (
SELECT TOP 1 A.RowID
FROM (
SELECT DENSE_RANK() OVER ( ORDER BY [month]) AS RowID ,
*
FROM dbo.Test_Table
) AS A
WHERE A.RowID <> A.[Month]
)
SELECT @Missing_Month
IF @Missing_Month IS NULL
BREAK
ELSE
INSERT INTO dbo.Test_Table
VALUES (2014, @Missing_Month)
SET @MinValue = @MinValue + 1
END
-- Check your results ---
SELECT A.*
FROM dbo.Test_Table AS A
LEFT JOIN dbo.Months_and_Years AS B ON A.[Month] = B.[Month]
WHERE B.[Month] IS NULL;