2

はい、同様の質問を何度も見つけることができますが、ここに投稿された最も洗練されたソリューションは、SQL Server では機能しますが、Sybase (私の場合は Sybase Anywhere 11) では機能しません。SQL Server の質問と重複しているとマークされた Sybase 関連の質問をいくつか見つけましたが、これは役に立ちません。

私が気に入ったがうまくいかなかった解決策の一例は、WITH ... DELETE ...コンストラクトです。

カーソルまたは while ループを使用して有効な解決策を見つけましたが、ループなしでそれが可能であることを願っています。

正確な重複を 1 つだけ残してすべて削除するだけで、素晴らしくシンプルで高速なクエリを期待しています。

テスト用の小さなフレームワークを次に示します。

IF OBJECT_ID( 'tempdb..#TestTable' ) IS NOT NULL
  DROP TABLE #TestTable;

CREATE TABLE #TestTable (Column1 varchar(1), Column2 int);

INSERT INTO #TestTable VALUES ('A', 1);
INSERT INTO #TestTable VALUES ('A', 1); -- duplicate
INSERT INTO #TestTable VALUES ('A', 1); -- duplicate
INSERT INTO #TestTable VALUES ('A', 2);
INSERT INTO #TestTable VALUES ('B', 1);
INSERT INTO #TestTable VALUES ('B', 2);
INSERT INTO #TestTable VALUES ('B', 2); -- duplicate
INSERT INTO #TestTable VALUES ('C', 1);
INSERT INTO #TestTable VALUES ('C', 2);

SELECT * FROM #TestTable ORDER BY Column1,Column2;

DELETE <your solution here>

SELECT * FROM #TestTable ORDER BY Column1,Column2;
4

5 に答える 5

1

これはうまく機能し、高速です。

DELETE FROM #TestTable
WHERE ROWID(#TestTable) IN (
  SELECT rowid FROM (
    SELECT ROWID(#TestTable) rowid, 
      ROW_NUMBER() OVER(PARTITION BY Column1,Column2 ORDER BY Column1,Column2) rownum
    FROM #TestTable
  ) sub
  WHERE rownum > 1
);

わからない場合はOVER(PARTITION BY ...)、内側のSELECTステートメントを実行して、その動作を確認してください。

于 2013-10-23T14:25:56.143 に答える
-1

機能がわかったので、ROWID()主キー (PK) を持つテーブルのソリューションを簡単に採用できます。これは、最初に保持するすべての行を選択してから、残りの行を削除します。

DELETE FROM #TestTable
FROM #TestTable
LEFT OUTER JOIN (
  SELECT MIN(ROWID(#TestTable)) rowid
  FROM #TestTable
  GROUP BY Column1, Column2
) AS KeepRows ON ROWID(#TestTable) = KeepRows.rowid
WHERE KeepRows.rowid IS NULL;

...または、この短いバリアントはどうですか? 好き!

DELETE FROM #TestTable
WHERE ROWID(#TestTable) NOT IN (
  SELECT MIN(ROWID(#TestTable))
  FROM #TestTable
  GROUP BY Column1, Column2
);

この投稿NOT INでは、私に最も影響を与えたのは、遅くなる可能性のあるコメントです。しかし、それはSQLサーバー用であり、エレガンスがより重要な場合もあります:)-すべては優れたインデックスに依存していると思います。

とにかく、通常、PK のないテーブルを持つのは悪い設計です。少なくとも「autoinc」ID を追加する必要があります。追加する場合は、ROWID()関数の代わりにその ID を使用できます。これは、Sybase による非標準の拡張機能です (他の一部にもあります)。

于 2013-10-24T06:15:43.623 に答える