各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

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

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

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

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

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

グッドジョブ、ESPN

グッドジョブ、ESPN

今日のホワイトハウスの記者会見で、報道官のサラ・ハッカビー・サンダースは、スポーツセンターのホストであるイェメル・ヒルのドナルド・トランプに関する最近のツイートについてコメントするよう求められ、大統領と彼の政策を白人至上主義者として説明した。ヒルは彼女のつぶやきのためにESPNによって公に叱責されました。

アマゾンからのこのレミントンツールセールで髪を整える、スタイルを整える、乾かす、または取り除く

アマゾンからのこのレミントンツールセールで髪を整える、スタイルを整える、乾かす、または取り除く

基本的に頭のあらゆる部分から髪の毛を整えたり、ブロードライしたり、まっすぐにしたり、脱毛したりする必要がある場合は、このレミントンゴールドボックスが最適です。今日だけ、Amazonは、すでに人気のあるShortcut Pro Self-HaircutKitやPearlPro Ceramic Flat Ironのように、グルーミングをはるかに簡単にするヘアツールをマークダウンしています。

カナダの元桂冠詩人が、史上最高の文化の盗用でトゥパックとマヤアンジェロウから盗んだ

カナダの元桂冠詩人が、史上最高の文化の盗用でトゥパックとマヤアンジェロウから盗んだ

トゥパックシャクール(ティムモーゼンフェルダー/ゲッティイメージズ); マヤアンジェロウ(マーティンゴッドウィン/ゲッティイメージズ)移動、テイラースウィフト。ケンドールとカイリーは、必要な数の座席を持っています。

テスラは、ハリケーンイルマによる避難を容易にするために、フロリダでの車両の範囲を拡大しています

テスラは、ハリケーンイルマによる避難を容易にするために、フロリダでの車両の範囲を拡大しています

写真:Tesla Motorsフロリダに住んでいて、Tesla Model S、Model X 60、またはModel 60Dを使用している場合、車の自律性は50 km(約30マイル)高くなります。これは失敗ではなく、ハリケーンイルマによる避難作業を容易にするために会社自身が命じた自治権の一時的な延長です。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

投資ノート:Bioscout AU$300万シード

投資ノート:Bioscout AU$300万シード

Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。

ムーアの法則を超えて

ムーアの法則を超えて

計算に対する私たちの欲求とムーアの法則が提供できるものとの間には、指数関数的に増大するギャップがあります。私たちの文明は計算に基づいています—建築と想像力の現在の限界を超える技術を見つけなければなりません。

Language