使用子句进行递归CTE查询

时间:2016-11-03 15:56:37

标签: sql-server

mytable数据

   ID_element Element1 Element2 DATE_Ele ID_Personne
        1       NULL     25      2002      1
        2       46     NULL      2003      1
        3       2      NULL      2004      1
        4       3       NULL     2005      1
        5       5      NULL      2006      1
        6      178      NULL    2007       1

工资 表薪水数据

ID_Personne       Date
1                  2007 

正如你在这个例子中看到的那样,首先我们得到两个表之间的日期值,在我们的例子中,它是2007,然后我们递增这个Date,直到Element1不为null而element2为null但是我更喜欢停止增量这个条件未经验证,正如您在此数据中看到的那样,2002年不符合我们的条件,因此我们在此步骤停止循环。

这是我的数据

set dateformat 'ymd'
Drop table #salary
CREATE TABLE #salary(
    ID_Personne int IDENTITY(1,1) PRIMARY KEY ,
    DATE_Per Date
)



--This is the data of my table:
INSERT INTO #salary VALUES ('2015-05-10')
INSERT INTO #salary VALUES ('2019-05-10')
INSERT INTO #salary VALUES ('2017-02-18')
INSERT INTO #salary VALUES ('2019-10-05')
INSERT INTO #salary VALUES ('2010-08-25')
INSERT INTO #salary VALUES ('2018-08-10')
INSERT INTO #salary VALUES ('2004-09-13')
INSERT INTO #salary VALUES ('2005-04-10')
INSERT INTO #salary VALUES ('2018-02-14')
INSERT INTO #salary VALUES ('2014-05-10')
INSERT INTO #salary VALUES ('2019-12-12')
INSERT INTO #salary VALUES ('2018-08-13')
INSERT INTO #salary VALUES ('2011-01-18')
INSERT INTO #salary VALUES ('2009-09-19')
INSERT INTO #salary VALUES ('2005-05-19')
INSERT INTO #salary VALUES ('2008-04-10')
INSERT INTO #salary VALUES ('2018-02-14')
INSERT INTO #salary VALUES ('2018-05-10')
INSERT INTO #salary VALUES ('2018-12-12')
INSERT INTO #salary VALUES ('2017-08-13')
INSERT INTO #salary VALUES ('2013-08-05')
INSERT INTO #salary VALUES ('2009-07-25')
INSERT INTO #salary VALUES ('2005-05-19')



Drop table #myTable
CREATE TABLE #myTable(
    ID_element int IDENTITY(200,1) PRIMARY KEY ,
    Element1 nvarchar(10),
    Element2 nvarchar(10),
    DATE_Ele Date,
    ID_Personne int
    FOREIGN KEY (ID_Personne)
    REFERENCES #salary (ID_Personne)

)

INSERT INTO #myTable VALUES ('A','B','2011-01-18',1)
INSERT INTO #myTable VALUES ('A','B','2009-09-19',2)
INSERT INTO #myTable VALUES ('A','B','2005-05-19',3)
INSERT INTO #myTable VALUES ('A','B','2008-04-10',4)
INSERT INTO #myTable VALUES ('A','B','2018-02-14',5)
INSERT INTO #myTable VALUES ('A','B','2018-05-10',6)
INSERT INTO #myTable VALUES ('A','B','2018-12-12',7)
INSERT INTO #myTable VALUES ('A','B','2004-03-20',8)
INSERT INTO #myTable VALUES ('A',NULL,'2018-02-14',9)
INSERT INTO #myTable VALUES ('A',NULL,'2014-02-14',9)
INSERT INTO #myTable VALUES ('A',NULL,'2015-02-14',9)
INSERT INTO #myTable VALUES ('A','B','2013-02-14',9)
INSERT INTO #myTable VALUES ('A',NULL,'2014-05-10',10)
INSERT INTO #myTable VALUES ('A',NULL,'2019-12-12',11)
INSERT INTO #myTable VALUES ('A',NULL,'2019-10-05',4)
INSERT INTO #myTable VALUES ('A',NULL,'2010-08-25',5)
INSERT INTO #myTable VALUES ('A',NULL,'2009-08-25',5)
INSERT INTO #myTable VALUES ('A',NULL,'2008-08-25',5)
INSERT INTO #myTable VALUES ('A','B','2007-03-25',5)
INSERT INTO #myTable VALUES ('A',NULL,'2018-08-10',6)
INSERT INTO #myTable VALUES ('A',NULL,'2004-09-13',7)
INSERT INTO #myTable VALUES ('A',NULL,'2005-04-10',8)
INSERT INTO #myTable VALUES ('A',NULL,'2009-07-25',10)
INSERT INTO #myTable VALUES ('A',NULL,'2005-05-19',11)
INSERT INTO #myTable VALUES ('A','B','2004-05-19',11)




Drop table #cteReports15
;WITH
  cteReports (ID_Personne, Annee)
  AS
  (
    SELECT t.ID_Personne, Year(t.DATE_Per) as Annee 
    FROM #salary as t
    Inner Join #myTable  as a
    ON t.ID_Personne=a.ID_Personne
    AND t.DATE_Per=a.DATE_Ele
    where a.Element1 is not null AND a.Element2 is null

    UNION ALL
    SELECT t.ID_Personne, Year(t.DATE_Per)-1 as Anneef 
   FROM #salary as t
    Inner Join #myTable  as a
    ON t.ID_Personne=a.ID_Personne
    AND t.DATE_Per=a.DATE_Ele
    Inner Join cteReports
    on cteReports.ID_Personne=a.ID_Personne

  )
  --Drop table #cteReports11
  Select Distinct ID_Personne, Annee 
INTO        #cteReports15
FROM        cteReports
OPTION (MAXRECURSION 1000);

1 个答案:

答案 0 :(得分:0)

我对你的要求不是很清楚。

但是,根据您在下面提供的结果,查询可能会对您有所帮助;

执行以下操作并检查

set dateformat 'ymd'
Drop table #salary
CREATE TABLE #salary(
    ID_Personne int IDENTITY(1,1) PRIMARY KEY ,
    DATE_Per Date
)



--This is the data of your table:
INSERT INTO #salary VALUES ('2015-05-10')
INSERT INTO #salary VALUES ('2019-05-10')
INSERT INTO #salary VALUES ('2017-02-18')
INSERT INTO #salary VALUES ('2019-10-05')
INSERT INTO #salary VALUES ('2010-08-25')
INSERT INTO #salary VALUES ('2018-08-10')
INSERT INTO #salary VALUES ('2004-09-13')
INSERT INTO #salary VALUES ('2005-04-10')
INSERT INTO #salary VALUES ('2018-02-14')
INSERT INTO #salary VALUES ('2014-05-10')
INSERT INTO #salary VALUES ('2019-12-12')
INSERT INTO #salary VALUES ('2018-08-13')
INSERT INTO #salary VALUES ('2011-01-18')
INSERT INTO #salary VALUES ('2009-09-19')
INSERT INTO #salary VALUES ('2005-05-19')
INSERT INTO #salary VALUES ('2008-04-10')
INSERT INTO #salary VALUES ('2018-02-14')
INSERT INTO #salary VALUES ('2018-05-10')
INSERT INTO #salary VALUES ('2018-12-12')
INSERT INTO #salary VALUES ('2017-08-13')
INSERT INTO #salary VALUES ('2013-08-05')
INSERT INTO #salary VALUES ('2009-07-25')
INSERT INTO #salary VALUES ('2005-05-19')



Drop table #myTable
CREATE TABLE #myTable(
    ID_element int IDENTITY(200,1) PRIMARY KEY ,
    Element1 nvarchar(10),
    Element2 nvarchar(10),
    DATE_Ele Date,
    ID_Personne int
    FOREIGN KEY (ID_Personne)
    REFERENCES #salary (ID_Personne)

)

INSERT INTO #myTable VALUES ('A','B','2011-01-18',1)
INSERT INTO #myTable VALUES ('A','B','2009-09-19',2)
INSERT INTO #myTable VALUES ('A','B','2005-05-19',3)
INSERT INTO #myTable VALUES ('A','B','2008-04-10',4)
INSERT INTO #myTable VALUES ('A','B','2018-02-14',5)
INSERT INTO #myTable VALUES ('A','B','2018-05-10',6)
INSERT INTO #myTable VALUES ('A','B','2018-12-12',7)
INSERT INTO #myTable VALUES ('A','B','2004-03-20',8)
INSERT INTO #myTable VALUES ('A',NULL,'2018-02-14',9)
INSERT INTO #myTable VALUES ('A',NULL,'2014-02-14',9)
INSERT INTO #myTable VALUES ('A',NULL,'2015-02-14',9)
INSERT INTO #myTable VALUES ('A','B','2013-02-14',9)
INSERT INTO #myTable VALUES ('A',NULL,'2014-05-10',10)
INSERT INTO #myTable VALUES ('A',NULL,'2019-12-12',11)
INSERT INTO #myTable VALUES ('A',NULL,'2019-10-05',4)
INSERT INTO #myTable VALUES ('A',NULL,'2010-08-25',5)
INSERT INTO #myTable VALUES ('A',NULL,'2009-08-25',5)
INSERT INTO #myTable VALUES ('A',NULL,'2008-08-25',5)
INSERT INTO #myTable VALUES ('A','B','2007-03-25',5)
INSERT INTO #myTable VALUES ('A',NULL,'2018-08-10',6)
INSERT INTO #myTable VALUES ('A',NULL,'2004-09-13',7)
INSERT INTO #myTable VALUES ('A',NULL,'2005-04-10',8)
INSERT INTO #myTable VALUES ('A',NULL,'2009-07-25',10)
INSERT INTO #myTable VALUES ('A',NULL,'2005-05-19',11)
INSERT INTO #myTable VALUES ('A','B','2004-05-19',11)
--end of your data insertions


--Query to perform the required result starts
DECLARE @RequiredData TABLE
(
 PersonID INT,
 SalaryYear INT,
Element1 nvarchar(10),
Element2 nvarchar(10)
)
DECLARE @PersonID as INT
DECLARE @SalaryDate DATE
DECLARE @yearcursor CURSOR 

SET @yearcursor =CURSOR FAST_FORWARD
FOR SELECT  ID_Personne,DATE_Per
   FROM  #salary  


OPEN @yearcursor   
FETCH NEXT FROM @yearcursor INTO @PersonID,@SalaryDate

WHILE @@FETCH_STATUS = 0   
BEGIN


IF EXISTS (SELECT ID_Personne,Year(DATE_Ele) SalryYear,Element1 ,Element2
 FROM  #myTable M
WHERE @PersonID=M.ID_Personne AND @SalaryDate=M.DATE_Ele
AND  Element1 IS NOT NULL AND Element2 IS NULL)
BEGIN
        INSERT INTO @RequiredData
        SELECT DISTINCT ID_Personne,Year(DATE_Ele) SalryYear,Element1 ,Element2
        FROM  #myTable M
        WHERE @PersonID=M.ID_Personne 
        AND  Element1 IS NOT NULL AND Element2 IS NULL AND  M.DATE_Ele=@SalaryDate
DECLARE @incrementerDate INT=Year(@SalaryDate)-1
DECLARE @IsValid BIT=1
DECLARE @MinYear INT= (SELECT MIN(YEAR(DATE_Ele)) FROM #myTable M WHERE @PersonID=M.ID_Personne AND Element1 IS NOT NULL AND Element2 IS NULL )


WHILE(@IsValid=1 AND @MinYear<=@incrementerDate)
BEGIN
IF EXISTS (SELECT ID_Personne,@incrementerDate SalryYear,Element1 ,Element2
 FROM  #myTable M
WHERE @PersonID=M.ID_Personne AND @incrementerDate=YEAR(M.DATE_Ele)
AND  Element1 IS NOT NULL AND Element2 IS NULL)

BEGIN
INSERT INTO @RequiredData
    SELECT ID_Personne,Year(DATE_Ele) SalryYear,Element1 ,Element2
    FROM  #myTable M
        WHERE @PersonID=M.ID_Personne 
        AND  Element1 IS NOT NULL AND Element2 IS NULL 
        AND  YEAR(M.DATE_Ele)=@incrementerDate
SET @incrementerDate=@incrementerDate-1
END

ELSE IF  EXISTS (SELECT ID_Personne,@incrementerDate SalryYear,Element1 ,Element2
 FROM  #myTable M
WHERE @PersonID=M.ID_Personne AND @incrementerDate=YEAR(M.DATE_Ele)
AND  Element1 IS NULL AND Element2 IS NOT NULL)
BEGIN
SET @IsValid=0
END

ELSE
BEGIN
    SET @incrementerDate=@incrementerDate-1
END
END
END


 FETCH NEXT FROM @yearcursor INTO  @PersonID,@SalaryDate
END

CLOSE @yearcursor
DEALLOCATE @yearcursor


SELECT * FROM @RequiredData ORDER BY PersonID,SalaryYear DESC

 There;
  • 我删除了公用表扩展并引入了一个游标
  • 光标将重复检查匹配的数据集以查找给定的人员ID和日期
  • 如果匹配,则检查给定用户的过去年份,其中Element1不为null且元素2为空并将它们插入临时表
  • 这将重复,直到迭代违反条件
  • 从临时表@RequiredData
  • 获取所需的输出