162

チームメンバーの名前とそのランキングを片手に保持するCompetitions結果テーブルがあります。

一方、一意の競合他社名のテーブルを維持する必要があります。

CREATE TABLE Competitors (cName nvarchar(64) primary key)

これで、最初のテーブルに約 200,000 件の結果があり、競合他社のテーブルが空の場合、これを実行できます。

INSERT INTO Competitors SELECT DISTINCT Name FROM CompResults

そしてクエリは、約 11,000 の名前を挿入するのにわずか 5 秒しかかかりません。

これまでのところ、これは重要なアプリケーションではないので、月に 1 回、約 10,000 行の新しい競争結果を受け取ったときに、競合他社テーブルを切り捨てることを検討できます。

しかし、新しい結果が追加され、新しい競合他社と既存の競合他社が追加された場合のベストプラクティスは何ですか? 既存の競合他社テーブルを切り詰めたくない

新しい競合他社に対してのみ INSERT ステートメントを実行する必要があり、競合他社が存在する場合は何もしません。

4

8 に答える 8

234

意味的には、「まだ存在しない競合他社を挿入する」ように求めています。

INSERT Competitors (cName)
SELECT DISTINCT Name
FROM CompResults cr
WHERE
   NOT EXISTS (SELECT * FROM Competitors c
              WHERE cr.Name = c.cName)
于 2011-03-13T09:21:10.067 に答える
60

もう1つのオプションは、結果テーブルを既存の競合他社のテーブルと左結合し、結合に一致しない個別のレコードをフィルタリングして新しい競合他社を見つけることです。

INSERT Competitors (cName)
SELECT  DISTINCT cr.Name
FROM    CompResults cr left join
        Competitors c on cr.Name = c.cName
where   c.cName is null

新しい構文MERGEは、それを行うためのコンパクトでエレガントかつ効率的な方法も提供します。

MERGE INTO Competitors AS Target
USING (SELECT DISTINCT Name FROM CompResults) AS Source ON Target.Name = Source.Name
WHEN NOT MATCHED THEN
    INSERT (Name) VALUES (Source.Name);
于 2011-03-13T12:21:30.790 に答える
32

なぜ他の人がまだこれを言っていないのかわかりません。

ノーマライズ。

競技を模した表はありますか?競技会は競技者で構成されていますか? 1 つまたは複数の競技会の競技者の個別のリストが必要です......

次のテーブルが必要です.....

CREATE TABLE Competitor (
    [CompetitorID] INT IDENTITY(1,1) PRIMARY KEY
    , [CompetitorName] NVARCHAR(255)
    )

CREATE TABLE Competition (
    [CompetitionID] INT IDENTITY(1,1) PRIMARY KEY
    , [CompetitionName] NVARCHAR(255)
    )

CREATE TABLE CompetitionCompetitors (
    [CompetitionID] INT
    , [CompetitorID] INT
    , [Score] INT

    , PRIMARY KEY (
        [CompetitionID]
        , [CompetitorID]
        )
    )

コンペティションコンペティターズ.コンペティションIDとコンペティターIDに制約があり、他のテーブルを指しています。

この種のテーブル構造では (キーはすべて単純な INTS です)、モデルに適合する適切な NATURAL KEY がないように思われるため、ここでは SURROGATE KEY が適していると思います。

したがって、これがある場合、特定の競技会の競合他社の個別のリストを取得するには、次のようなクエリを発行できます。

DECLARE @CompetitionName VARCHAR(50) SET @CompetitionName = 'London Marathon'

    SELECT
        p.[CompetitorName] AS [CompetitorName]
    FROM
        Competitor AS p
    WHERE
        EXISTS (
            SELECT 1
            FROM
                CompetitionCompetitor AS cc
                JOIN Competition AS c ON c.[ID] = cc.[CompetitionID]
            WHERE
                cc.[CompetitorID] = p.[CompetitorID]
                AND cc.[CompetitionName] = @CompetitionNAme
        )

また、競合他社が参加している各競技のスコアが必要な場合は、次のようになります。

SELECT
    p.[CompetitorName]
    , c.[CompetitionName]
    , cc.[Score]
FROM
    Competitor AS p
    JOIN CompetitionCompetitor AS cc ON cc.[CompetitorID] = p.[CompetitorID]
    JOIN Competition AS c ON c.[ID] = cc.[CompetitionID]

また、新しい競合他社との新しい競合がある場合は、競合他社テーブルに既に存在するものを確認するだけです。それらが既に存在する場合は、それらの競合他社に対して競合他社に挿入せず、新しい競合他社に対して挿入します。

次に、新しいコンペティションをコンペティションに挿入し、最後にすべてのリンクをコンペティションコンペティターに作成します。

于 2011-03-13T10:06:14.633 に答える
12

テーブルを結合して、まだ存在しない独自の競合他社のリストを取得する必要がありますCompetitors

これにより、一意のレコードが挿入されます。

INSERT Competitors (cName) 
SELECT DISTINCT Name
FROM CompResults cr LEFT JOIN Competitors c ON cr.Name = c.cName
WHERE c.Name IS NULL

固有の名前の選択を待つことができずに、この挿入を迅速に行う必要がある時が来るかもしれません。その場合、一意の名前を一時テーブルに挿入し、その一時テーブルを使用して実際のテーブルに挿入できます。一時テーブルに挿入するときにすべての処理が行われるため、これはうまく機能し、実際のテーブルには影響しません。次に、すべての処理が終了したら、実際のテーブルにすばやく挿入します。実際のテーブルに挿入する最後の部分をトランザクション内にラップすることさえあります。

于 2011-03-13T08:35:38.447 に答える