web-dev-qa-db-ja.com

INNER JOINに対するDISTINCTクエリ

2つのテーブルがあります。1つ(ARTISTS)には、さまざまなアーティスト、詳細、伝記のリストが含まれていますが、画像は含まれていません。必要な画像を含む、オークション結果が満載の別のテーブル(ARCHIVECATALOGUES)があります。 ARTISTSテーブルからすべての詳細を取得し、アーティストごとに他のテーブルからのイメージ(どちらでもかまいません)を含めるクエリを生成したいと思います。

したがって、2つのテーブルをINNER JOINsするクエリが必要です。以下のクエリは、ARCHIVESCATALOGUEテーブルからすべての結果、つまりアーティストごとの複数の結果を取得しています。ただし、アーティストごとに1つの結果のみが必要です。 artist.ArtistIDフィールドでDISTINCTを使用しましたが、役に立ちませんでした。これがコードです:

SELECT DISTINCT artist.ArtistID
    ,ArchiveCatalogues.IMAGER
    ,ArchiveCatalogues.AUCTION
    ,artist.surname
    ,artist.firstnames
    ,artist.dates
    ,artist.honorific
    ,artist.biog
FROM artist
INNER JOIN ArchiveCatalogues ON (ArchiveCatalogues.ARTIST = artist.surname)
    AND (ArchiveCatalogues.FIRSTNAME = artist.firstnames)
WHERE artist.surname >= H *
    AND artist.surname < I
GROUP BY artist.surname
    ,artist.firstnames
    ,artist.dates
    ,artist.honorific
    ,artist.biog
    ,ArchiveCatalogues.AUCTION
    ,artist.ArtistID
    ,ArchiveCatalogues.IMAGER

おそらく、OUTER JOINを使用する必要がありますか?

1
HonestCon

まず(よくある誤解)、distinctは個々の列には適用されません。得られるのは、distinct行です。これはGROUP BYとまったく同じであるため、distinctは冗長です。

第二に、あなたが興味のある(またはランダムなものを取得する)重複の中のどの行を決定する必要があります。ウィンドウ関数を使用して、アーティストごとにArchiveCataloguesを列挙することでこれを実現できます。

 SELECT artist.ArtistID
    ,ArchiveCatalogues.IMAGER
    ,ArchiveCatalogues.AUCTION
    ,artist.surname
    ,artist.firstnames
    ,artist.dates
    ,artist.honorific
    ,artist.biog
    , row_number() over (partition by artist.ArtistID
                      -- add wanted order her as:
                      -- order by ...
                        ) as rn
FROM artist
JOIN ArchiveCatalogues 
    ON ArchiveCatalogues.ARTIST = artist.surname
   AND ArchiveCatalogues.FIRSTNAME = artist.firstnames
WHERE artist.surname >= H *
  AND artist.surname < I

目的がわからないので、グループを削除したことに注意してください。ここから最初の行を選択できます。

SELECT ArtistID
     , IMAGER
     , AUCTION
     , surname
     , firstnames
     , dates
     , honorific
     , biog
FROM (
    SELECT artist.ArtistID
        ,ArchiveCatalogues.IMAGER
        ,ArchiveCatalogues.AUCTION
        ,artist.surname
        ,artist.firstnames
        ,artist.dates
        ,artist.honorific
        ,artist.biog
        , row_number() over (partition by artist.ArtistID
                          -- add wanted order her as:
                          -- order by ...
                            ) as rn
    FROM artist
    JOIN ArchiveCatalogues 
        ON ArchiveCatalogues.ARTIST = artist.surname
       AND ArchiveCatalogues.FIRSTNAME = artist.firstnames
    WHERE artist.surname >= H *
      AND artist.surname < I
) as T
WHERE rn = 1;

結合は奇妙に見えますが、テーブルとそれらのキーがどのように見えるかを知らなければ分からないでしょう。

3
Lennart

DISTINCTは、クエリで次に配置した列だけでなく、SELECTステートメントのすべての列に適用されます。現在、DISTINCTとGROUP BYはまったく同じことを行っています。

あなたはグループ化によって本質的に言っています:

以下の組み合わせごとに1つのレコードが必要です。

artist.surname
,artist.firstnames
,artist.dates
,artist.honorific
,artist.biog
,ArchiveCatalogues.AUCTION
,artist.ArtistID
,ArchiveCatalogues.IMAGER

その特定の順序で。基本的に、一意のレコードと見なすものの疑似キーを作成しています。

「プライマリ」テーブルであるため、クエリは実際にはARTISTから結果を取得していますですが、これは、内部結合するテーブルであるため、ArchiveCataloguesテーブルに一致するレコードのみです(オン姓+名)。

他のテーブルと一致するかどうかに関係なく、両方のテーブルからレコードを探している場合は、FULL OUTER JOINを使用できますが、このシナリオではそれが必要だとは思いません。

1
MguerraTorres

ここでの問題は、クエリが必要な画像を知る方法がないため、関連するすべての画像が得られることです。 JOINに別のものを追加するか、GROUP関数を使用できます

簡単にするために、テーブルが見えないことを考えると、ArchiveCatalogueテーブルにはなんらかの一意の識別子が含まれていると想定するので、これを使用して行ごとに1つのイメージを選択できます。

 SELECT artist.ArtistID
,ArchiveCatalogues.IMAGER
,ArchiveCatalogues.AUCTION
,artist.surname
,artist.firstnames
,artist.dates
,artist.honorific
,artist.biog
,MAX(ArchiveCatalogue.PRIMARYKEY)

FROM artist
INNER JOIN ArchiveCatalogues ON
ArchiveCatalogues.ARTIST = artist.surname AND 
ArchiveCatalogues.FIRSTNAME = artist.firstnames

WHERE artist.surname >= H *
AND artist.surname < I

GROUP BY  artist.ArtistID
,ArchiveCatalogues.IMAGER
,ArchiveCatalogues.AUCTION
,artist.surname
,artist.firstnames
,artist.dates
,artist.honorific
,artist.biog

MAX(Archive.Key)は、ID列の最大値を選択します。これは、最新の画像である可能性があります。 JOINでフィルタリングする方が効率的だと思いますが、これは読みやすいと思います

1
cockbeard