web-dev-qa-db-ja.com

1つの列でSELECT DISTINCTを実行し、他の列を返しますか?

3つのルックアップテーブルを使用して必要なすべての情報を取得するクエリがあります。 1つの列にDISTINCT値が必要ですが、それに関連付けられた残りのデータも必要です。

私のSQLコード:

SELECT acss_lookup.ID AS acss_lookupID,
   acss_lookup.product_lookupID AS acssproduct_lookupID,
   acss_lookup.region_lookupID AS acssregion_lookupID,
   acss_lookup.document_lookupID AS acssdocument_lookupID,
   product.ID AS product_ID,
   product.parent_productID AS productparent_product_ID,
   product.label AS product_label,
   product.displayheading AS product_displayheading,
   product.displayorder AS product_displayorder,
   product.display AS product_display,
   product.ignorenewupdate AS product_ignorenewupdate,
   product.directlink AS product_directlink,
   product.directlinkURL AS product_directlinkURL,
   product.shortdescription AS product_shortdescription,
   product.logo AS product_logo,
   product.thumbnail AS product_thumbnail,
   product.content AS product_content,
   product.pdf AS product_pdf,
   product.language_lookupID AS product_language_lookupID,
   document.ID AS document_ID,
   document.shortdescription AS document_shortdescription,
   document.language_lookupID AS document_language_lookupID,
   document.document_note AS document_document_note,
   document.displayheading AS document_displayheading
FROM acss_lookup
     INNER JOIN product ON (acss_lookup.product_lookupID = product.ID)
     INNER JOIN document ON (acss_lookup.document_lookupID = document.ID)
ORDER BY product_displayheading ASC;

このクエリからすべての製品を取得したいのですが、検索アプリケーションのドロップダウンメニューにデータを入力しているので、一度だけ取得したいのです。ユーザーがその表にある製品から選択できるようにしたい(そのため、製品が1度だけ必要になる)。

これは複雑すぎませんか?より単純化されたアプローチを使用する必要がありますか?

12
stephmoreland

まだ言及されていないもう1つのアプローチは、ウィンドウ関数を使用することです。たとえば、row_number:

   SELECT * FROM  
   (
   SELECT acss_lookup.ID AS acss_lookupID, 
   ROW_NUMBER() OVER 
   (PARTITION BY your_distinct_column ORDER BY any_column_you_think_is_appropriate)
   as num,
   acss_lookup.product_lookupID AS acssproduct_lookupID,
   acss_lookup.region_lookupID AS acssregion_lookupID,
   acss_lookup.document_lookupID AS acssdocument_lookupID,
   product.ID AS product_ID,
   product.parent_productID AS productparent_product_ID,
   product.label AS product_label,
   product.displayheading AS product_displayheading,
   product.displayorder AS product_displayorder,
   product.display AS product_display,
   product.ignorenewupdate AS product_ignorenewupdate,
   product.directlink AS product_directlink,
   product.directlinkURL AS product_directlinkURL,
   product.shortdescription AS product_shortdescription,
   product.logo AS product_logo,
   product.thumbnail AS product_thumbnail,
   product.content AS product_content,
   product.pdf AS product_pdf,
   product.language_lookupID AS product_language_lookupID,
   document.ID AS document_ID,
   document.shortdescription AS document_shortdescription,
   document.language_lookupID AS document_language_lookupID,
   document.document_note AS document_document_note,
   document.displayheading AS document_displayheading
   FROM acss_lookup
     INNER JOIN product ON (acss_lookup.product_lookupID = product.ID)
     INNER JOIN document ON (acss_lookup.document_lookupID = document.ID)
   )a
   WHERE a.num = 1
   ORDER BY product_displayheading ASC;
7
a1ex07

これにはいくつかの方法があります。私が使用する2つの主なものは、共通のテーブル式とサブクエリです。 CTEを使用すると、クエリは次のようになります。

WITH theResultSet AS
(
    SELECT DISTINCT(column) AS col1 FROM some.table
)
SELECT whatever
  FROM more.data AS a
  JOIN theResultSet as b ON a.col1 = b.col1
  /* additional joins, clauses etc...*/

またはサブクエリを使用:

SELECT whatever
  FROM more.data AS a
  JOIN (SELECT DISTINCT(column) AS col1 FROM some.table) AS b ON a.col1 = b.col1
/* additional joins, clauses etc... */

私は通常、どちらがより速いかをテストし、それを使います。

これがお役に立てば幸いです。

4
Mr.Brownstone

(あなたがしようとしていることは、各結果行を単一の製品に「折りたたむ」ことだと思うので、この答えはその仮定に基づいています。)

これは不可能です。他のテーブルから関連する1 .. *データを取得するには、他の列で重複する値を返す必要があります。

通常、これを処理する方法は、クエリをそのまま実行し、結合された結果セットをアプリケーションコードで処理することです。私は通常、キー値に基づいてコレクション内の各タイプの個別のエンティティで終わるハッシュコレクションアプローチを使用してこれを行います。

このアプローチはネットワークトラフィックの点でコストが高くなりますが、通常、複数のクエリを実行し、アプリケーションコードで必要に応じて結果をつなぎ合わせるなどの方法を実行する方が望ましいです。これは、クエリの実行頻度や返されるデータの量など、多くの要因に依存します。

1
Jon Seigel