1

実行に数時間かかる TSQL ステートメントがあります。重複が挿入されるのを避けるために、インポート プロセスを調べる必要があると確信していますが、当面は、重複する値を持つレコードを除くすべてのレコードを削除したいと思います。ParameterValueId はテーブルの主キーですが、削除する必要がある重複したエントリが多数あります。ParameterId、SiteId、MeasurementDateTime、および ParameterValue ごとに 1 つのレコードのみが必要です。以下は、重複レコードを削除するための現在の方法です。It finds all values that have a count > 1. 次に、それらの値を持つ最初の Id を見つけ、それらの値で見つかった最初の ID と一致しない値を持つすべてのレコードを削除します。print ステートメント以外に、これを行うより効率的な方法があります。パフォーマンスを向上させるためにカーソルを使用する方法はありますか?

BEGIN TRANSACTION

SET NOCOUNT ON

DECLARE @BeginningRecordCount INT
SET @BeginningRecordCount =
(
    SELECT COUNT(*) 
    FROM ParameterValues
)

DECLARE @ParameterId UNIQUEIDENTIFIER
DECLARE @SiteId UNIQUEIDENTIFIER
DECLARE @MeasurementDateTime DATETIME
DECLARE @ParameterValue FLOAT


DECLARE CDuplicateValues CURSOR FOR
SELECT 
     [ParameterId]
    ,[SiteId]
    ,[MeasurementDateTime]
    ,[ParameterValue]
FROM [ParameterValues]
GROUP BY
     [ParameterId]
    ,[SiteId]
    ,[MeasurementDateTime]
    ,[ParameterValue]
HAVING COUNT(*) > 1

OPEN CDuplicateValues
FETCH NEXT FROM CDuplicateValues INTO
     @ParameterId
    ,@SiteId
    ,@MeasurementDateTime
    ,@ParameterValue

DECLARE @FirstParameterValueId UNIQUEIDENTIFIER
DECLARE @DuplicateRecordsDeleting INT
WHILE @@FETCH_STATUS <> -1
BEGIN
    SET @FirstParameterValueId =
    (
        SELECT TOP 1 ParameterValueId
        FROM ParameterValues
        WHERE
                ParameterId = @ParameterId
            AND SiteId = @SiteId
            AND MeasurementDateTime = @MeasurementDateTime
            AND ParameterValue = @ParameterValue
    )

    SET @DuplicateRecordsDeleting =
    (
        SELECT COUNT(*)
        FROM ParameterValues
        WHERE
                ParameterId = @ParameterId
            AND SiteId = @SiteId
            AND MeasurementDateTime = @MeasurementDateTime
            AND ParameterValue = @ParameterValue
            AND ParameterValueId <> @FirstParameterValueId
    )

    PRINT 'DELETING ' + CAST(@DuplicateRecordsDeleting AS NVARCHAR(50))
        + ' records with values ParameterId : ' + CAST(@ParameterId AS NVARCHAR(50))
        + ', SiteId : ' + CAST (@SiteId AS NVARCHAR(50))
        + ', MeasurementDateTime : ' + CAST(@MeasurementDateTime AS NVARCHAR(50))
        + ', ParameterValue : ' + CAST(@ParameterValue AS NVARCHAR(50))

    DELETE FROM ParameterValues
        WHERE
                ParameterId = @ParameterId
            AND SiteId = @SiteId
            AND MeasurementDateTime = @MeasurementDateTime
            AND ParameterValue = @ParameterValue
            AND ParameterValueId <> @FirstParameterValueId

    FETCH NEXT FROM CDuplicateValues INTO
         @ParameterId
        ,@SiteId
        ,@MeasurementDateTime
        ,@ParameterValue
END
CLOSE CDuplicateValues
DEALLOCATE CDuplicateValues

DECLARE @EndingRecordCount INT
SET @EndingRecordCount =
(
    SELECT COUNT(*) 
    FROM ParameterValues
)

PRINT 'Beginning Record Count   :   ' + CAST(@BeginningRecordCount AS NVARCHAR(50))
PRINT 'Ending Record Count      :   ' + CAST(@EndingRecordCount AS NVARCHAR(50))
PRINT 'Total Records Deleted    :   ' + CAST((@BeginningRecordCount - @EndingRecordCount) AS NVARCHAR(50))

SET NOCOUNT OFF

PRINT 'RUN THE COMMIT OR ROLLBACK STATEMENT AFTER VERIFYING DATA.'
--COMMIT
--ROLLBACK
4

2 に答える 2

1

あなたは単一のSQLでそれを行うことができます:

DELETE p FROM ParameterValues p
LEFT JOIN
(SELECT ParameterId, SiteId, MeasurementDateTime, ParameterValue, MAX(ParameterValueId) AS MAX_PARAM
 FROM ParameterValues
 GROUP BY ParameterId, SiteId, MeasurementDateTime, ParameterValue
) m
ON m.ParameterId = p.ParameterId
  AND m.SiteId = p.SiteId
  AND m.MeasurementDateTime = p.MeasurementDateTime
  AND m.ParameterValue = p.ParameterValue
  AND m.MAX_PARAM = p.ParameterValueId
WHERE m.ParameterId IS NULL

もちろん、出力は印刷されませんが、前後の行を印刷することはできます

于 2013-04-30T03:57:49.677 に答える