0

サーバー側コードのユーザー名フィールドの大文字と小文字の区別のために、誤ってデータが複数回保存されたデータを保存するテーブルがあります。ユーザー名フィールドは大文字と小文字を区別しないと見なす必要があります。表の重要な列とデータは以下にあります。

私の要件は、最新の保存データを除くすべてを削除することです。私はこのためのSQLスクリプトを作成しており、重複しているすべての行を識別することから始めました。この選択により、次のようなテーブルが返されます。

各行の最新の保存は、存在する場合はLASTUPDATEDDATEであり、存在しない場合はCREATEDDATEです。この例では、「username」の最新の保存は行3になります。

ID CREATEDDATE LASTUPDATEDDATE USERNAME                           
--------------- --------------- --------
12011年11月11日ユーザー名                                
2011年11月1日2011年11月2日ユーザー名                            
32012年1月8日ユーザー名      

私のスクリプト(重複したユーザー名が表示されるすべての行を選択します)は次のようになります。


SELECT 
  id, createddate, lastupdateddate, username
FROM
  table
WHERE
  LOWER(username)
IN
  (
    SELECT 
      LOWER(username)
    FROM 
      table
    GROUP BY 
      LOWER(username)
    HAVING 
      COUNT(*) > 1
  )  
ORDER BY
  LOWER(username)

今の私の質問は、行3以外のすべてを選択するにはどうすればよいですか?Stack Overflowでこの質問に一致するものを検索しましたが、十分に一致するものが見つかりませんでした。私はおそらく何らかの参加をしなければならないことを知っていますが、それについて頭を悩ませることはできません。正しい方向へのプッシュに本当に感謝します。

おそらくかなり新しいバージョンのSQLServerを使用しています。

4

2 に答える 2

1

重複を削除するには、次を使用できます。

with todelete as (
     select t.*,
            row_number() over (partition by lower(username) order by createddate desc) as seqnum
     from table
    )
delete from t
where seqnum > 1

これにより、各行に連続番号が割り当てられ、最新の1から始まります。次に、最新のものを除くすべてを削除します。

2つの日付については、次を使用できます。

with todelete as (
     select t.*,
            row_number() over (partition by lower(username) order by thedate desc) as seqnum
     from (select t.*,
                  (case when createddate >= coalesdce(updateddate, createddate)
                        then createddate 
                        else updateddate
                   end) as thedate
           from table
          ) t
    )
delete from t
where seqnum > 1
于 2013-02-20T15:30:06.387 に答える
1

注意すべき点がいくつかありLOWERます。クエリで使用する理由はありません。SQLServerではA=a。

また、正しい日付を取得するにはCOALESCE、LastUpdatedDateが存在するかどうかを判断し、存在する場合はそれで並べ替え、そうでない場合はCreatedDateで並べ替えることができます。

それをまとめると、これはうまくいくはずです:

DELETE T
FROM YourTable T 
  JOIN (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY username  
                   ORDER BY COALESCE(lastupdateddate, createddate) DESC) as RN
     FROM YourTable
    ) T2 ON T.Id = T2.Id
WHERE T2.RN > 1

これがフィドルのサンプルです:http ://www.sqlfiddle.com/#!3/51f7c/1

@Gordonが正しく示唆しているように、使用しているSQL Serverのバージョン(2005以降)によっては、CTEを使用することもできます。

WITH CTE AS (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY username  
                               ORDER BY COALESCE(lastupdateddate, createddate) DESC) as RN
     FROM YourTable
    ) 
DELETE FROM CTE WHERE RN > 1
于 2013-02-20T15:45:42.020 に答える