2017-02-08 10 views
3

私は問題の解決方法を開発しました(私は思っています)、これについてもっと良い方法があるかどうかを知りたいと思います。より良い方法があります。SQL Server:ユニークな行を表示するために日付を検索する

問題:会社名と移動日が表示されます。同社は離れることができ、別の会社が来て元の会社が戻ってくる可能性があります。この問題を少し難解にするには、そこにある会社の不正な日付があるかもしれません。それを説明する最良の方法は、テーブルを介しです:

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 

より効率的な方法でこれを行う方法上の任意の提案、または何らかのエラーが発見された場合、フィードバックは非常に高く評価されています

私が持っているコードです。

おかげで、

レオは

+1

はあなたにも予想される出力を表示することができますか? –

+0

セットベースのアプローチは、ギャップ/アイランドアプローチ、またはLEAD()/ LAG()アプローチのいずれかを使用して、このループよりも優れています。 –

答えて

1

ラグ()

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 
+2

これまでにLAGについて聞いたことがない新しいことを毎日学びますが、このシナリオには完璧です。どうもありがとうございました! – Leonidas199x

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 
+0

答えに時間をとってくれて本当にありがとう、これも動作し、私のソリューションよりもはるかに綺麗です。 – Leonidas199x

関連する問題