各GROUPBYグループの最初の行を選択しますか?

1441
David Wolever 2010-09-27 15:23.

タイトルが示すように、でグループ化された行の各セットの最初の行を選択したいと思いますGROUP BY

具体的には、purchases次のようなテーブルがある場合:

SELECT * FROM purchases;

私の出力:

id | 顧客| 合計
--- + ---------- + ------
 1 | ジョー| 5
 2 | サリー| 3
 3 | ジョー| 2
 4 | サリー| 1

それぞれが行っidた最大の購入(total)のを照会したいと思いますcustomer。このようなもの:

SELECT FIRST(id), customer, FIRST(total)
FROM  purchases
GROUP BY customer
ORDER BY total DESC;

期待される出力:

FIRST(id)| 顧客| FIRST(合計)
---------- + ---------- + -------------
        1 | ジョー| 5
        2 | サリー| 3

17 answers

1212
OMG Ponies 2010-09-27 15:27.

Oracle 9.2 +(最初に述べたように、8i +ではない)、SQL Server 2005以降、PostgreSQL 8.4以降、DB2、Firebird 3.0以降、Teradata、Sybase、Vertica:

WITH summary AS (
    SELECT p.id, 
           p.customer, 
           p.total, 
           ROW_NUMBER() OVER(PARTITION BY p.customer 
                                 ORDER BY p.total DESC) AS rk
      FROM PURCHASES p)
SELECT s.*
  FROM summary s
 WHERE s.rk = 1

任意のデータベースでサポート:

ただし、関係を解消するにはロジックを追加する必要があります。

  SELECT MIN(x.id),  -- change to MAX if you want the highest
         x.customer, 
         x.total
    FROM PURCHASES x
    JOIN (SELECT p.customer,
                 MAX(total) AS max_total
            FROM PURCHASES p
        GROUP BY p.customer) y ON y.customer = x.customer
                              AND y.max_total = x.total
GROUP BY x.customer, x.total
1232
Erwin Brandstetter 2011-10-03 16:21.

ではPostgreSQLのこれは通常、簡単で高速(以下、よりパフォーマンスの最適化):

SELECT DISTINCT ON (customer)
       id, customer, total
FROM   purchases
ORDER  BY customer, total DESC, id;

または、出力列の序数で(明確でない場合は)短くします。

SELECT DISTINCT ON (2)
       id, customer, total
FROM   purchases
ORDER  BY 2, 3 DESC, 1;

totalNULLにすることができる場合(どちらの方法でも問題はありませんが、既存のインデックスと一致させる必要があります):

...
ORDER  BY customer, total DESC NULLS LAST, id;

主なポイント

DISTINCT ONは標準のPostgreSQL拡張です(リストDISTINCT全体でのみSELECT定義されています)。

DISTINCT ON句に任意の数の式をリストします。結合された行の値は重複を定義します。マニュアル:

明らかに、2つの行は、少なくとも1つの列値が異なる場合、別個のものと見なされます。この比較では、NULL値は等しいと見なされます。

大胆な強調鉱山。

DISTINCT ONと組み合わせることができますORDER BY。の先頭の式はORDER BY、の式のセットに含まれている必要がありますが、DISTINCT ONそれらの間で自由に順序を並べ替えることができます。例。
あなたは追加することができ、追加する式をORDER BYピアの各グループから特定の行を選択します。または、マニュアルに記載されているように:

DISTINCT ON式(複数可)、左端一致しなければならないORDER BY表現(複数可)。ORDER BY句は、通常、それぞれの中の行の所望の優先順位を決定する追加の式(S)含有するであろうDISTINCT ON基。

id結びつきを断ち切るために最後の項目として追加しました:
id各グループから最も小さい行を選択して、最も高いものを共有しtotalます。」

グループごとの最初のクエリを決定する並べ替え順序と一致しない方法で結果を並べ替えるには、クエリの上にあるクエリを別のクエリにネストしますORDER BY。例。

場合はtotalNULLにすることができます、あなたはおそらく最大のnull以外の値を持つ行をしたいです。NULLS LAST示されているように追加します。見る:

  • 列ASCで並べ替えますが、最初にNULL値ですか?

SELECTリストは、中の式によって制約されていないDISTINCT ONか、ORDER BYどのような方法で。(上記の単純なケースでは必要ありません):

  • あなたはする必要はありませんで、式のいずれかを含みますDISTINCT ONORDER BY

  • リストには他の式を含めることができますSELECT。これは、はるかに複雑なクエリをサブクエリや集計/ウィンドウ関数に置き換えるのに役立ちます。

私はPostgresバージョン8.3– 13でテストしましたが、この機能は少なくともバージョン7.1から存在しているので、基本的には常にそうです。

インデックス

上記のクエリの完全なインデックスは、3つの列すべてに一致する順序で、一致する並べ替え順序を持つ複数列のインデックスです。

CREATE INDEX purchases_3c_idx ON purchases (customer, total DESC, id);

専門的すぎるかもしれません。ただし、特定のクエリの読み取りパフォーマンスが重要な場合は、これを使用してください。あなたが持っている場合はDESC NULLS LAST、クエリでは、そのソート順が一致するように、インデックスに同じを使用して、インデックスが適用されます。

有効性/パフォーマンスの最適化

クエリごとに調整されたインデックスを作成する前に、コストとメリットを比較検討してください。上記のインデックスの可能性は、データの分布に大きく依存します

インデックスは、事前にソートされたデータを提供するために使用されます。Postgres 9.2以降では、インデックスが基になるテーブルよりも小さい場合、クエリはインデックスのみのスキャンの恩恵を受けることもできます。ただし、インデックス全体をスキャンする必要があります。

以下のために、いくつかの顧客ごとの行(列内の高カーディナリティcustomer)、これは非常に効率的です。とにかくソートされた出力が必要な場合はさらにそうです。顧客あたりの行数が増えると、メリットは縮小します。
理想的には、work_memRAMで関連するソート手順を処理するのに十分であり、ディスクにこぼれないようにする必要があります。ただし、一般的に設定work_mem すぎると、悪影響が生じる可能性があります。SET LOCAL非常に大きなクエリを検討してください。で必要な量を見つけますEXPLAIN ANALYZE。ソートステップでの「ディスク:」の言及は、さらに多くの必要性を示しています。

  • Linux上のPostgreSQLの構成パラメーターwork_mem
  • ORDERBYの日付とテキストを使用して単純なクエリを最適化する

以下のために多くの顧客ごとの行(列で低カーディナリティcustomer)、緩いインデックス・スキャン(「スキャンスキップ」別名)は(かなり)より効率的であるが、Postgresの13まで実装されていないこと(索引のみのスキャンのための実装はですPostgres 14の開発。こことここを参照してください。)
今のところ、これに代わるより高速なクエリ手法があります。特に、固有の顧客を保持する別のテーブルがある場合は、これが一般的な使用例です。しかし、そうでない場合も:

  • GROUP BYクエリを最適化して、ユーザーごとに最新の行を取得します
  • グループごとの最大クエリを最適化する
  • 行ごとに最後のN個の関連行をクエリします

基準

ここに簡単なベンチマークがありましたが、これは今では時代遅れです。この別の回答で、詳細なベンチマークに置き換えました。

145
Erwin Brandstetter 2016-01-11 20:05.

基準

Postgresので最も興味深い候補者のテスト9.49.5の途中で現実的なテーブルと200K行purchasesおよび10K明確なcustomer_id顧客あたり平均20行)。

Postgres 9.5では、実質的に86446の異なる顧客を対象に2番目のテストを実行しました。以下を参照してください(顧客あたり平均2.3行)。

セットアップ

メインテーブル

CREATE TABLE purchases (
  id          serial
, customer_id int  -- REFERENCES customer
, total       int  -- could be amount of money in Cent
, some_column text -- to make the row bigger, more realistic
);

serial(PK制約を以下に追加)と整数を使用しcustomer_idます。これは、より一般的な設定だからです。またsome_column、通常はより多くの列を補うために追加されました。

ダミーデータ、PK、インデックス-一般的なテーブルには、いくつかのデッドタプルもあります。

INSERT INTO purchases (customer_id, total, some_column)    -- insert 200k rows
SELECT (random() * 10000)::int             AS customer_id  -- 10k customers
     , (random() * random() * 100000)::int AS total     
     , 'note: ' || repeat('x', (random()^2 * random() * random() * 500)::int)
FROM   generate_series(1,200000) g;

ALTER TABLE purchases ADD CONSTRAINT purchases_id_pkey PRIMARY KEY (id);

DELETE FROM purchases WHERE random() > 0.9; -- some dead rows

INSERT INTO purchases (customer_id, total, some_column)
SELECT (random() * 10000)::int             AS customer_id  -- 10k customers
     , (random() * random() * 100000)::int AS total     
     , 'note: ' || repeat('x', (random()^2 * random() * random() * 500)::int)
FROM   generate_series(1,20000) g;  -- add 20k to make it ~ 200k

CREATE INDEX purchases_3c_idx ON purchases (customer_id, total DESC, id);

VACUUM ANALYZE purchases;

customer テーブル-優れたクエリの場合:

CREATE TABLE customer AS
SELECT customer_id, 'customer_' || customer_id AS customer
FROM   purchases
GROUP  BY 1
ORDER  BY 1;

ALTER TABLE customer ADD CONSTRAINT customer_customer_id_pkey PRIMARY KEY (customer_id);

VACUUM ANALYZE customer;

私の中で第二のテスト9.5のための私は、同じ設定を使用しますが、としてrandom() * 100000生成するcustomer_idあたりわずか数行を取得しますcustomer_id

テーブルのオブジェクトサイズ purchases

この関連する回答から取得したクエリで生成されます。

  • PostgreSQLテーブルの行のサイズを測定する
               what                | bytes/ct | bytes_pretty | bytes_per_row
-----------------------------------+----------+--------------+---------------
 core_relation_size                | 20496384 | 20 MB        |           102
 visibility_map                    |        0 | 0 bytes      |             0
 free_space_map                    |    24576 | 24 kB        |             0
 table_size_incl_toast             | 20529152 | 20 MB        |           102
 indexes_size                      | 10977280 | 10 MB        |            54
 total_size_incl_toast_and_indexes | 31506432 | 30 MB        |           157
 live_rows_in_text_representation  | 13729802 | 13 MB        |            68
 ------------------------------    |          |              |
 row_count                         |   200045 |              |
 live_tuples                       |   200045 |              |
 dead_tuples                       |    19955 |              |

クエリ

1. row_number()CTEでは(他の回答を参照)

WITH cte AS (
   SELECT id, customer_id, total
        , row_number() OVER(PARTITION BY customer_id ORDER BY total DESC) AS rn
   FROM   purchases
   )
SELECT id, customer_id, total
FROM   cte
WHERE  rn = 1;

  1. row_number() サブクエリで(私の最適化)
SELECT id, customer_id, total
FROM   (
   SELECT id, customer_id, total
        , row_number() OVER(PARTITION BY customer_id ORDER BY total DESC) AS rn
   FROM   purchases
   ) sub
WHERE  rn = 1;

3. DISTINCT ON(他の回答を参照)

SELECT DISTINCT ON (customer_id)
       id, customer_id, total
FROM   purchases
ORDER  BY customer_id, total DESC, id;

4.LATERALサブクエリを使用したrCTE (ここを参照)

WITH RECURSIVE cte AS (
   (  -- parentheses required
   SELECT id, customer_id, total
   FROM   purchases
   ORDER  BY customer_id, total DESC
   LIMIT  1
   )
   UNION ALL
   SELECT u.*
   FROM   cte c
   ,      LATERAL (
      SELECT id, customer_id, total
      FROM   purchases
      WHERE  customer_id > c.customer_id  -- lateral reference
      ORDER  BY customer_id, total DESC
      LIMIT  1
      ) u
   )
SELECT id, customer_id, total
FROM   cte
ORDER  BY customer_id;

5.customerテーブルLATERAL(ここを参照)

SELECT l.*
FROM   customer c
,      LATERAL (
   SELECT id, customer_id, total
   FROM   purchases
   WHERE  customer_id = c.customer_id  -- lateral reference
   ORDER  BY total DESC
   LIMIT  1
   ) l;

6. array_agg()with ORDER BY(他の回答を参照)

SELECT (array_agg(id ORDER BY total DESC))[1] AS id
     , customer_id
     , max(total) AS total
FROM   purchases
GROUP  BY customer_id;

結果

上記のクエリの実行時間EXPLAIN ANALYZE(およびすべてのオプションがオフ)、ベスト5回の実行

すべてのクエリは、(他の手順の中でも)インデックスのみのスキャンを使用しましたpurchases2_3c_idx。インデックスのサイズを小さくするためだけのものもあれば、より効果的なものもあります。

A. Postgres 9.4、20万行、1つあたり約20 customer_id

1. 273.274 ms  
2. 194.572 ms  
3. 111.067 ms  
4.  92.922 ms  
5.  37.679 ms  -- winner
6. 189.495 ms

B. Postgres9.5と同じ

1. 288.006 ms
2. 223.032 ms  
3. 107.074 ms  
4.  78.032 ms  
5.  33.944 ms  -- winner
6. 211.540 ms  

C. B.と同じですが、1つあたり約2.3行です。 customer_id

1. 381.573 ms
2. 311.976 ms
3. 124.074 ms  -- winner
4. 710.631 ms
5. 311.976 ms
6. 421.679 ms

関連するベンチマーク

これは、Postgres 11.5(2019年9月現在)で1,000万行と60kの一意の「顧客」を使用した「ogr」テストによる新しいものです。結果は、これまでに見たものとまだ一致しています。

  • 個々の識別子の最新の行にアクセスする適切な方法は?

2011年からの元の(古い)ベンチマーク

私は、PostgreSQLとの3つのテストを実行した9.1関わる3つの列のそれぞれに65579行と単一列のbtreeインデックスの実際のテーブルの上に、最高のかかった実行時間5つの実行のを。@OMGPoniesの最初のクエリ()を上記のソリューション()
と比較します。ADISTINCT ONB

  1. テーブル全体を選択します。この場合、5958行になります。
A: 567.218 ms
B: 386.673 ms
  1. WHERE customer BETWEEN x AND y1000行になる条件を使用します。
A: 249.136 ms
B:  55.111 ms
  1. で単一の顧客を選択しWHERE customer = xます。
A:   0.143 ms
B:   0.072 ms

他の回答に記載されているインデックスで同じテストを繰り返しました

CREATE INDEX purchases_3c_idx ON purchases (customer, total DESC, id);

1A: 277.953 ms  
1B: 193.547 ms

2A: 249.796 ms -- special index not used  
2B:  28.679 ms

3A:   0.120 ms  
3B:   0.048 ms
59
TMS 2013-06-27 22:38.

これは一般的なグループごとの最大の問題であり、すでに十分にテストされ、高度に最適化されたソリューションがあります。個人的には、Bill Karwinによる左結合ソリューション(他の多くのソリューションを含む元の投稿)が好きです。

この一般的な問題に対する解決策の束は、驚くべきことに、最も公式なソースの1つであるMySQLマニュアルに記載されていることに注意してください。一般的なクエリの例を参照してください::特定の列のグループごとの最大値を保持する行。

31
Paul A Jungwirth 2014-08-28 08:14.

Postgresでは次のarray_aggように使用できます。

SELECT  customer,
        (array_agg(id ORDER BY total DESC))[1],
        max(total)
FROM purchases
GROUP BY customer

これidにより、各顧客の最大の購入額がわかります。

注意すべきいくつかの事柄:

  • array_aggは集計関数であるため、で機能しGROUP BYます。
  • array_aggスコープをそれ自体に限定する順序を指定できるため、クエリ全体の構造を制約することはありません。デフォルトとは異なることを行う必要がある場合に、NULLをソートする方法の構文もあります。
  • 配列を作成したら、最初の要素を取得します。(Postgres配列は0インデックスではなく、1インデックスです)。
  • array_agg3番目の出力列にも同様の方法で使用できますが、max(total)より簡単です。
  • とは異なりDISTINCT ON、を使用array_aggすると、GROUP BY他の理由で必要な場合に備えて、を保持できます。
15
gyan 2013-06-18 08:02.

SubQが存在するため、Erwinが指摘したようにソリューションはあまり効率的ではありません。

select * from purchases p1 where total in
(select max(total) from purchases where p1.customer=customer) order by total desc;
12
khaled_gomaa 2018-03-25 06:11.

クエリ:

SELECT purchases.*
FROM purchases
LEFT JOIN purchases as p 
ON 
  p.customer = purchases.customer 
  AND 
  purchases.total < p.total
WHERE p.total IS NULL

それはどのように機能しますか?(私はそこに行ったことがある)

購入ごとに合計が最も多くなるようにしたいのです。


いくつかの理論的なもの(クエリを理解したいだけの場合は、この部分をスキップしてください)

Totalを関数T(customer、id)とし、名前とIDを指定して値を返します。指定された合計(T(customer、id))が最大であることを証明するには、次のいずれかを証明する必要があります。

  • ∀xT(customer、id)> T(customer、x)(この合計は、その顧客の他のすべての合計よりも高くなります)

または

  • ¬∃xT(customer、id)<T(customer、x)(その顧客の合計はこれ以上ありません)

最初のアプローチでは、私が本当に好きではないその名前のすべてのレコードを取得する必要があります。

2つ目は、これより高いレコードはあり得ないと言う賢い方法が必要になります。


SQLに戻る

名前と合計が結合されたテーブルよりも少ないテーブルを結合したままにした場合:

LEFT JOIN purchases as p 
ON 
p.customer = purchases.customer 
AND 
purchases.total < p.total

同じユーザーの合計が多い別のレコードを持つすべてのレコードが参加するようにします。

+--------------+---------------------+-----------------+------+------------+---------+
| purchases.id |  purchases.customer | purchases.total | p.id | p.customer | p.total |
+--------------+---------------------+-----------------+------+------------+---------+
|            1 | Tom                 |             200 |    2 | Tom        |     300 |
|            2 | Tom                 |             300 |      |            |         |
|            3 | Bob                 |             400 |    4 | Bob        |     500 |
|            4 | Bob                 |             500 |      |            |         |
|            5 | Alice               |             600 |    6 | Alice      |     700 |
|            6 | Alice               |             700 |      |            |         |
+--------------+---------------------+-----------------+------+------------+---------+

これにより、グループ化を必要とせずに、購入ごとに最大の合計をフィルタリングできます。

WHERE p.total IS NULL
    
+--------------+----------------+-----------------+------+--------+---------+
| purchases.id | purchases.name | purchases.total | p.id | p.name | p.total |
+--------------+----------------+-----------------+------+--------+---------+
|            2 | Tom            |             300 |      |        |         |
|            4 | Bob            |             500 |      |        |         |
|            6 | Alice          |             700 |      |        |         |
+--------------+----------------+-----------------+------+--------+---------+

そしてそれが私たちに必要な答えです。

10
matiu 2015-03-11 05:19.

私はこのように使用します(postgresqlのみ): https://wiki.postgresql.org/wiki/First/last_%28aggregate%29

-- Create a function that always returns the first non-NULL item
CREATE OR REPLACE FUNCTION public.first_agg ( anyelement, anyelement )
RETURNS anyelement LANGUAGE sql IMMUTABLE STRICT AS $$ SELECT $1;
$$; -- And then wrap an aggregate around it CREATE AGGREGATE public.first ( sfunc = public.first_agg, basetype = anyelement, stype = anyelement ); -- Create a function that always returns the last non-NULL item CREATE OR REPLACE FUNCTION public.last_agg ( anyelement, anyelement ) RETURNS anyelement LANGUAGE sql IMMUTABLE STRICT AS $$
        SELECT $2; $$;

-- And then wrap an aggregate around it
CREATE AGGREGATE public.last (
        sfunc    = public.last_agg,
        basetype = anyelement,
        stype    = anyelement
);

次に、例はほぼそのまま機能するはずです。

SELECT FIRST(id), customer, FIRST(total)
FROM  purchases
GROUP BY customer
ORDER BY FIRST(total) DESC;

警告:のNULL行は無視されます


編集1-代わりにpostgres拡張機能を使用する

今私はこのように使用します: http://pgxn.org/dist/first_last_agg/

ubuntu 14.04にインストールするには:

apt-get install postgresql-server-dev-9.3 git build-essential -y
git clone git://github.com/wulczer/first_last_agg.git
cd first_last_app
make && sudo make install
psql -c 'create extension first_last_agg'

これは、最初と最後の機能を提供するpostgres拡張機能です。上記の方法よりも明らかに速い。


編集2-順序付けとフィルタリング

集計関数(これらのような)を使用する場合、データを既に並べ替える必要なしに、結果を並べ替えることができます。

http://www.postgresql.org/docs/current/static/sql-expressions.html#SYNTAX-AGGREGATES

したがって、順序付けを使用した同等の例は次のようになります。

SELECT first(id order by id), customer, first(total order by id)
  FROM purchases
 GROUP BY customer
 ORDER BY first(total);

もちろん、アグリゲート内に収まると思われる順序でフィルタリングすることもできます。非常に強力な構文です。

8
Alejandro Salamanca Mazuelo 2014-04-09 06:13.

非常に高速なソリューション

SELECT a.* 
FROM
    purchases a 
    JOIN ( 
        SELECT customer, min( id ) as id 
        FROM purchases 
        GROUP BY customer 
    ) b USING ( id );

テーブルがidでインデックス付けされている場合、非常に高速です。

create index purchases_id on purchases (id);
8
Diwas Poudel 2018-12-30 06:12.

SQL Serverでは、次のことができます。

SELECT *
FROM (
SELECT ROW_NUMBER()
OVER(PARTITION BY customer
ORDER BY total DESC) AS StRank, *
FROM Purchases) n
WHERE StRank = 1

説明:ここでは、顧客に基づいてグループ化を行い、合計で注文します。その後、各グループにStRankというシリアル番号が付けられ、StRankが1の最初の1人の顧客を取り出します。

8
Valentin Podkamennyi 2019-04-05 10:54.

PostgreSQL、U-SQL、IBM DB2、およびGoogle BigQuerySQLのARRAY_AGG関数を使用します。

SELECT customer, (ARRAY_AGG(id ORDER BY total DESC))[1], MAX(total)
FROM purchases
GROUP BY customer
3
Johnny Wong 2017-01-05 05:47.

受け入れられたOMGPoniesの「あらゆるデータベースでサポートされている」ソリューションは、私のテストからはかなりの速度です。

ここでは、同じアプローチですが、より完全でクリーンな任意のデータベースソリューションを提供します。同点が考慮され(顧客ごとに1行のみを取得したい場合、顧客ごとの最大合計に対して複数のレコードを取得したい場合でも)、購入テーブルの実際に一致する行に対して他の購入フィールド(purchase_payment_idなど)が選択されます。

任意のデータベースでサポート:

select * from purchase
join (
    select min(id) as id from purchase
    join (
        select customer, max(total) as total from purchase
        group by customer
    ) t1 using (customer, total)
    group by customer
) t2 using (id)
order by customer

このクエリは、特に購入テーブルに(customer、total)のような複合インデックスがある場合、かなり高速です。

リマーク:

  1. t1、t2はサブクエリエイリアスであり、データベースによっては削除できます。

  2. 警告:このusing (...)句は、2017年1月のこの編集の時点で、MS-SQLおよびOracleデータベースでは現在サポートされていませんon t2.id = purchase.id。自分でegなどに拡張する必要があります。USING構文はSQLite、MySQL、およびPostgreSQLで機能します。

3
Lukasz Szozda 2019-11-18 11:19.

Snowflake / Teradataは、ウィンドウ関数のQUALIFYようHAVINGに機能する句をサポートしています。

SELECT id, customer, total
FROM PURCHASES
QUALIFY ROW_NUMBER() OVER(PARTITION BY p.customer ORDER BY p.total DESC) = 1
2
pbillen 2019-12-10 02:49.

PostgreSQLでは、別の可能性は、first_valueウィンドウ関数をSELECT DISTINCT:と組み合わせて使用することです。

select distinct customer_id,
                first_value(row(id, total)) over(partition by customer_id order by total desc, id)
from            purchases;

コンポジットを作成した(id, total)ので、両方の値が同じ集計によって返されます。もちろん、いつでもfirst_value()2回申請できます。

1
Eugen Konkov 2018-09-29 03:50.
  • 集約された行のセットから(特定の条件によって)任意の行を選択する場合。

  • sum/avgに加えて別の()集計関数を使用する場合max/min。したがって、手がかりを使用することはできませんDISTINCT ON

次のサブクエリを使用できます。

SELECT  
    (  
       SELECT **id** FROM t2   
       WHERE id = ANY ( ARRAY_AGG( tf.id ) ) AND amount = MAX( tf.amount )   
    ) id,  
    name,   
    MAX(amount) ma,  
    SUM( ratio )  
FROM t2  tf  
GROUP BY name

amount = MAX( tf.amount )1つの制限で任意の条件に置き換えることができます:このサブクエリは複数の行を返さないようにする必要があります

しかし、そのようなことをしたいのであれば、おそらくウィンドウ関数を探しています

1
BazSTR 2019-01-19 00:59.

SQl Serverの場合、最も効率的な方法は次のとおりです。

with
ids as ( --condition for split table into groups
    select i from (values (9),(12),(17),(18),(19),(20),(22),(21),(23),(10)) as v(i) 
) 
,src as ( 
    select * from yourTable where  <condition> --use this as filter for other conditions
)
,joined as (
    select tops.* from ids 
    cross apply --it`s like for each rows
    (
        select top(1) * 
        from src
        where CommodityId = ids.i 
    ) as tops
)
select * from joined

使用済み列のクラスター化インデックスを作成することを忘れないでください

1
uncle bob 2020-07-17 17:40.

このようにそれは私のために働きます:

SELECT article, dealer, price
FROM   shop s1
WHERE  price=(SELECT MAX(s2.price)
              FROM shop s2
              WHERE s1.article = s2.article
              GROUP BY s2.article)
ORDER BY article;

各記事の最高価格を選択してください

Related questions

MORE COOL STUFF

「水曜日」シーズン1の中心には大きなミステリーがあります

「水曜日」シーズン1の中心には大きなミステリーがあります

Netflixの「水曜日」は、典型的な10代のドラマ以上のものであり、実際、シーズン1にはその中心に大きなミステリーがあります.

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ケイト・ミドルトンは、州の夕食会と州の訪問中にカミラ・パーカー・ボウルズからスポットライトを奪いたくなかった、と専門家は言う.

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンが、オリビア・ワイルドが彼女とハリー・スタイルズとの間の「難しい」が「非常に友好的」な分割を恒久的にすることを望んでいる理由を見つけてください.

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする 

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする&nbsp;

エリザベス女王の死後、ケイト・ミドルトンが舞台裏で「非常に困難な時期」を過ごしていたと伝えられている理由を調べてください.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

Total War:Warhammer:Kotakuレビュー

Total War:Warhammer:Kotakuレビュー

私はこのゲームを嫌う準備ができていました。先週の前に、Total War:Warhammerについての私の考えがありました:それでもここに私は、私の手にある完成品であり、私は変わった男です。

涙の道:軍事化された帝国主義勢力がスタンディングロックキャンプを占領

涙の道:軍事化された帝国主義勢力がスタンディングロックキャンプを占領

スタンディングロックスー族のメンバーと水の保護者は、ノースダコタ州のスタンディングロックにあるオセティサコウィンキャンプを去ります。(Twitter経由のCNNスクリーンショット)火と煙がスカイラインを覆い、スタンディングロックスー族のメンバーと水の保護者が、聖なるものを守りながら建てた家、オセティサコウィン(セブンカウンシルファイアーズ)キャンプから行進し、太鼓を打ち、歌い、祈りました。ダコタアクセスパイプラインとしても知られる「ブラックスネーク」からの土地。

シアーズとKマートはイヴァンカ・トランプの商品を自分たちで取り除いています

シアーズとKマートはイヴァンカ・トランプの商品を自分たちで取り除いています

写真:APシアーズとKマートは、イヴァンカ・トランプのトランプホームアイテムのコレクションも、誰も購入したくないために削除しました。シアーズとKマートの両方の親会社であるシアーズホールディングスは、土曜日のABCニュースへの声明で、彼らが気にかけていると辛抱強く説明しましたトランプラインを売り続けるにはお金を稼ぐことについてあまりにも多く。

ポテトチップスでたった10分でスペインのトルティーヤを作る

ポテトチップスでたった10分でスペインのトルティーヤを作る

伝統的なスペインのトルティーヤは通常、オリーブオイルで柔らかくなるまで調理されたポテトから始まります(30分以上かかる場合があります)が、ケトルで調理されたポテトチップスの助けを借りてわずか10分でテーブルに置くことができます。上のビデオはすべてがバラバラにならないように裏返す方法を含め、レシピ全体を説明しますが、必要なのは4〜5個の卵と3カップのケトルチップスだけです。

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、子供向けのパズルの本の序文を書き、ジョージ王子、シャーロット王女、ルイ王子と一緒にテキストを読むと述べた.

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

Yak's Produce は、数十個のつぶれたメロンを野生動物のリハビリ専門家であるレスリー グリーンと彼女のルイジアナ州の救助施設で暮らす 42 匹の動物に寄付しました。

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

8 枚目のスタジオ アルバムのリリースに向けて準備を進めているデミ ロヴァートは、「スーパー グレート ガイ」と付き合っている、と情報筋は PEOPLE に確認しています。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

ホームオフィスのセットアップ術を極めよう!AppExert の開発者は、家族全員が一緒にいる場合でも、在宅勤務の技術を習得しています。祖父や曽祖父が共同家族で暮らしていた頃の記憶がよみがえりました。

2022 年、私たちのデジタル ライフはどこで終わり、「リアル ライフ」はどこから始まるのでしょうか?

20 年前のタイムトラベラーでさえ、日常生活におけるデジタルおよびインターネットベースのサービスの重要性に驚くことでしょう。MySpace、eBay、Napster などのプラットフォームは、高速化に焦点を合わせた世界がどのようなものになるかを示してくれました。

ニューロマーケティングの秘密科学

ニューロマーケティングの秘密科学

マーケティング担当者が人間の欲望を操作するために使用する、最先端の (気味が悪いと言う人もいます) メソッドを探ります。カートをいっぱいにして 3 桁の領収書を持って店を出る前に、ほんの数点の商品を買いに行ったことはありませんか? あなたは一人じゃない。

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

私たちが住んでいる世界を確実に理解するには、データが必要です。ただし、空間参照がない場合、このデータは地理的コンテキストがないと役に立たなくなる可能性があります。

Language