5

私は次のようなpostgresテーブルを持っています:

id | user_id | state | created_at

状態は次のいずれかになります。

new, paying, paid, completing, complete, payment_failed, completion_failed

次のレポートを返すステートメントが必要です。

  1. 日付ごとのすべての支払済み州の合計
  2. 完了したすべての州の日付別の合計
  3. カウントされるのは、ユーザーごとに1日1つだけで、日付ごとのすべての新しい、有料の、完了した状態の合計
  4. すべてのpayment_failed、completion_failedの日付ごとの合計で、ユーザーごとに1日1つだけカウントされます

これまでのところ私はこれを持っています:

SELECT
  DATE(created_at) AS date,
  SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete,
  SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at)

進行中の状態と失敗した状態の合計は、これを選択に追加することで十分に簡単です。

SUM(CASE WHEN state IN('new','paying','completing') THEN 1 ELSE 0 END) AS in_progress,
SUM(CASE WHEN state IN('payment_failed','completion_failed') THEN 1 ELSE 0 END) AS failed 

しかし、user_idごとに1日1つだけin_progressを作成し、失敗した状態をカウントする方法を理解するのに苦労しています。

これが必要な理由は、統計で失敗率を操作するためです。失敗または不完全な注文をトリガーする多くのユーザーは、さらにトリガーして失敗率を膨らませます。

よろしくお願いします。

4

2 に答える 2

3
SELECT created_at::date AS the_date
      ,SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete
      ,SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid
      ,COUNT(DISTINCT CASE WHEN state IN('new','paying','completing')
                      THEN user_id ELSE NULL END) AS in_progress
      ,COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed')
                      THEN user_id ELSE NULL END) AS failed 
FROM   orders
WHERE  created_at BETWEEN ? AND ?
GROUP  BY created_at::date

the_dateキーワード date を識別子として使用することは (許可されていても) 賢明ではないため、エイリアスとして使用します。

completeとに同様の手法を使用できますpaid。一方は他方と同じくらい優れています。

COUNT(CASE WHEN state = 'complete' THEN 1 ELSE NULL END) AS complete
于 2013-01-11T21:55:01.810 に答える
2

次のようなものを試してください:

SELECT
  DATE(created_at) AS date,
  SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete,
  SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid,
  COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') THEN user_id ELSE NULL END) AS in_progress,
  COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') THEN user_id ELSE NULL END) AS failed
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at);

主なアイデア -COUNT (DISTINCT ...)一意の値user_idをカウントし、NULL値をカウントしません。

詳細:集約関数4.2.7. 集計式

同じスタイルのクエリ全体がカウントされ、単純化されCASE WHEN ...ます。

SELECT
  DATE(created_at) AS date,
  COUNT(CASE WHEN state = 'complete' THEN 1 END) AS complete,
  COUNT(CASE WHEN state = 'paid' THEN 1 END) AS paid,
  COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') THEN user_id END) AS in_progress,
  COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') THEN user_id END) AS failed
FROM orders
WHERE created_at BETWEEN ? AND ?
GROUP BY DATE(created_at);
于 2013-01-11T21:53:14.647 に答える