SQL Server:查找日期中断以显示唯一行

时间:2017-02-08 14:27:42

标签: sql sql-server tsql

我已经开发出一个问题的解决方案(我认为),我很想知道是否有更好的解决方法,因为我不禁觉得有更好的方法。

问题:显示公司名称和日期移动。该公司可以离开,另一家公司进来,然后原来的公司可以回来。为了使这个问题有点棘手,那里的公司可能会有流氓日期。解释它的最佳方式是通过表格:

Table example

我需要提取的,只是公司第一次入住,直到被其他公司破坏等等。

我的代码是:

IF OBJECT_ID('tempdb..#tmpData') IS NOT NULL 
   DROP TABLE #tmpData
GO

CREATE TABLE #tmpData
(
    COMPANY_NAME NVARCHAR(30),
    DATE_MOVED_IN DATETIME,
    ID INT IDENTITY(1,1),
    UNIQUE_ID INT
)

INSERT INTO #tmpData(COMPANY_NAME, DATE_MOVED_IN)
    SELECT 'ABC LTD','01/01/2017' UNION ALL
    SELECT 'ABC LTD','01/04/2017' UNION ALL
    SELECT 'XYZ LTD','01/10/2017' UNION ALL
    SELECT 'ABC LTD','01/12/2017';

DECLARE @intMinID INT,
        @intMaxID INT,
        @strNextComp NVARCHAR(50),
        @strCurrentComp NVARCHAR(50),
        @strPreviousComp NVARCHAR(50),
        @intMaxUID INT;

SELECT  
    @intMinID = MIN(TD.ID),
    @intMaxID = MAX(TD.ID)
FROM    
    #tmpData AS TD

UPDATE TD
SET TD.UNIQUE_ID = 1
FROM #tmpData AS TD
WHERE TD.ID = @intMinID;

WHILE @intMinID <= @intMaxID
BEGIN
    SELECT  
        @strCurrentComp = TD.COMPANY_NAME
    FROM    
        #tmpData AS TD
    WHERE   
        TD.ID = @intMinID;

    SELECT  
        @strNextComp = TD.COMPANY_NAME
    FROM    
        #tmpData AS TD
    WHERE   
        TD.ID = (@intMinID + 1)

    SELECT  
        @strPreviousComp = CASE WHEN EXISTS (SELECT 1
                                             FROM #tmpData AS TD
                                             WHERE TD.ID = (@intMinID - 1))
                                    THEN TD.COMPANY_NAME
                                    ELSE 'No Company Exists'
                           END
    FROM    
        #tmpData AS TD
    WHERE   
        TD.ID = (@intMinID - 1)

    SELECT  
        @intMaxUID = MAX(TD.UNIQUE_ID)
    FROM    
        #tmpData AS TD

    IF(@strPreviousComp IS NULL)
        PRINT 'Nothing to do'
    ELSE IF((@strCurrentComp <> @strNextComp) AND (@strCurrentComp = @strPreviousComp)) 
    BEGIN   
        UPDATE TD
        SET TD.UNIQUE_ID = @intMaxUID
        FROM #tmpData AS TD
        WHERE TD.ID = @intMinID;
    END
    ELSE
    BEGIN
        UPDATE TD
        SET TD.UNIQUE_ID = @intMaxUID + 1
        FROM #tmpData AS TD
        WHERE TD.ID = @intMinID;
    END 

    SET @intMinID = @intMinID + 1;
END

SELECT   
    COMPANY_NAME, MIN(DATE_MOVED_IN) AS DATE_MOVED_IN
FROM
    #tmpData
GROUP BY 
    COMPANY_NAME, UNIQUE_ID
ORDER BY 
    UNIQUE_ID ASC

有关如何以更有效的方式执行此操作的任何建议,或者如果发现任何错误,我们非常感谢您提供反馈。

谢谢,

利奥

2 个答案:

答案 0 :(得分:1)

Lag()应该这样做......

with CTE as
(
select Company_Name, Date_Moved_in, lag(Company_Name) over (order by Date_Moved_In) as PrevComp
from #TempTable
)
select Company_Name, Date_Moved_In
from CTE
where PrevComp <> Company_Name
or PrevComp is null

答案 1 :(得分:1)

您可以使用行号逻辑中的差异将公司的连续日期分类到一个组中。单独运行内部查询以查看如何分配组。

此后,只有group by公司和之前分类的小组才能获得第一个日期。

select company_name,min(date_moved_in) 
from (
select t.*,
row_number() over(order by date_moved_in)
-row_number() over(partition by company_name order by date_moved_in) as grp
from #tmpData t
) x
group by company_name,grp