6

ここで問題が発生しました。簡単な解決策があることを願っています。これをできるだけ簡単にしようとします:

  • チケットは出席者のものです
  • 例:

select * from tickets JOIN attendees ON attendee.id = tickets.attendee_id
  • 出席者には、「収益」と呼ばれる 10 進数の列があります。

とはいえ、総収益など、チケットに関するさまざまな情報を返すクエリを実行する必要があります。問題は、2 つのチケットが同じ出席者に属している場合、収益が 2 回カウントされることです。出席者の収益を 1 回だけ合計するにはどうすればよいですか?

私のORMがこれを困難にするため、サブクエリを使用したくありません。さらに、複数の列に対してこれを実行したい場合、サブクエリソリューションはスケーリングしません。

ここに私が持っているものがあります:

  • 収益が 100 の参加者 1 人
  • 両方ともその出席者に属する 2 枚のチケット

Select count(tickets.*) as tickets_count
     , sum(attendees.revenue) as atendees_revenue
from tickets LEFT OUTER JOIN attendees ON attendees.id = tickets.attendee_id;

=> これattendees_revenueは 200 であることを示しています。私はそれを 100 にしたいと考えています。データベースには 100 の existing_revenue を持つ出席者が 1 人いるためです。出席者が二重にカウントされることは望ましくありません。

これが可能かどうか教えてください。

4

4 に答える 4

8

subquery なしで結果を取得するには、高度なウィンドウ関数のトリックに頼る必要があります。

SELECT sum(count(*))       OVER () AS tickets_count
     , sum(min(a.revenue)) OVER () AS atendees_revenue
FROM   tickets   t
JOIN   attendees a ON a.id = t.attendee_id
GROUP  BY t.attendee_id
LIMIT  1;

sqlfiddle

それはどのように機能しますか?

これを理解するための鍵は、クエリ内の一連のイベントです。

集約関数 -> ウィンドウ関数 -> DISTINCT -> LIMIT

詳細:

ステップバイステップ:

  1. I GROUP BY t.attendee_id- 通常はサブクエリで行います。

  2. 次に、カウントを合計して、チケットの総数を取得します。あまり効率的ではありませんが、要件によって強制されます。集計関数count(*)はウィンドウ関数でラップされsum( ... ) OVER ()、あまり一般的ではない式に到達します: sum(count(*)) OVER ().

    そして、出席者ごとの最小収益を合計して、重複のない合計を取得します。

    出席者ごとのすべての行で同じであることが保証されているため、同じ効果を得るためにmax()oravg()の代わりに使用することもできます。min()revenue

    ウィンドウ関数で許可されていれば、これはより簡単になる可能性がありDISTINCTますが、PostgreSQL は (まだ) この機能を実装していません。ドキュメントごと

    集約ウィンドウ関数は、通常の集約関数とは異なり、関数の引数リスト内で使用できないDISTINCTか、使用できません。ORDER BY

  3. 最後のステップは、単一の行を取得することです。DISTINCTすべての行が同じであるため、これは (SQL 標準) で実行できます。LIMIT 1ただし、高速になります。または SQL 標準フォームFETCH FIRST 1 ROWS ONLY.

于 2012-11-01T01:05:30.243 に答える
-3

あなたは実際にはかなり近かったです。これを行うには多くの方法があり、あなたの質問を正しく理解していれば、これでうまくいくはずです:

SELECT
   COUNT(*) AS ticketsCount,
   SUM(DISTINCT attendees.revenue) AS revenueSum
FROM
   tickets
   LEFT JOIN attendees ON
      attendees.id = tickets.attendee_id
于 2012-11-01T00:56:57.700 に答える