2016-06-02 8 views
3

を見つけるために、私はそうのようなクエリがあると表示します。Postgresは、ネストされたSQLクエリまたはどのように最後のINET

のように見えます
SELECT DISTINCT(orders.email), uuid_nil() AS customer_id, 'Order' AS customer_type, orders.first_name, orders.last_name, MAX(orders.paid_at) AS last_order_at, 1 AS order_count, SUM(orders.total_price_cents) AS total_spent_pennies 
FROM orders 
WHERE orders.state = 'paid' AND orders.customer_id IS null 
GROUP BY orders.email, customer_id, orders.first_name, orders.last_name 
UNION 
SELECT DISTINCT(customers.email), customers.id AS customer_id, 'Customer' AS customer_type, customers.first_name, customers.last_name, MAX(orders.paid_at) AS last_order_at, COUNT(orders.*) AS order_count, SUM(orders.total_price_cents) AS total_spent_pennies 
FROM customers 
JOIN orders ON customers.id = orders.customer_id 
GROUP BY customers.email, customers.id, customers.first_name, customers.last_name 

:私の質問は、私は彼らの最後を含めることができる方法である

+-------------------------------+--------------------------------------+---------------+------------+--------------+-------------------------+-------------+---------------------+ 
| email       | customer_id       | customer_type | first_name | last_name | last_order_at   | order_count | total_spent_pennies | 
+-------------------------------+--------------------------------------+---------------+------------+--------------+-------------------------+-------------+---------------------+ 
| [email protected]    | 00000000-0000-0000-0000-000000000000 | Order   | Richard | Doe   | 2015-12-18 14:45:22 UTC | 1   | 2000    | 
| [email protected]     | 00000000-0000-0000-0000-000000000000 | Order   | Paul  | Doe   | 2016-04-05 09:04:57 UTC | 1   | 5000    | 
+-------------------------------+--------------------------------------+---------------+------------+--------------+-------------------------+-------------+---------------------+ 

IPアドレス(INET列)。ある日、私は単純にMAX集約関数を使うことができますが、IPアドレスは明らかに1つ持っていません。

は基本的に私はこのクエリを組み合わせることができますどのように上記のようなものを私に彼らのlast_ipアドレスを持つ新しい列を与えるために:

SELECT browser_ip FROM orders 
WHERE email = '[email protected]' 
ORDER BY paid_at DESC 
LIMIT 1 

答えて

1

このような簡単なサブクエリを使用すると、おそらくクエリの名前を間に入れておく必要があります。

http://www.techonthenet.com/postgresql/subqueries.php

たとえば、クエリの最初の部分は次のようなものになるだろう:

SELECT DISTINCT(c1.email), c1.id AS customer_id, 'Customer' AS customer_type, 
c1.first_name, c1.last_name, MAX(orders.paid_at) AS last_order_at, 
COUNT(orders.*) AS order_count, SUM(orders.total_price_cents) AS total_spent_pennies, 
(SELECT browser_ip FROM orders WHERE c1.email = orders.email 
ORDER BY paid_at DESC LIMIT 1) last_ip 
FROM customers c1 
JOIN orders ON c1.id = orders.customer_id 
GROUP BY c1.email, c1.id, c1.first_name, c1.last_name 
0

Cast to varchar、および使用string_agg - 何かのように:

SELECT email, paid_at, string_agg(browser_ip::varchar, ',') as ips 
WHERE email = '[email protected]' 
GROUP BY email, paid_at 
ORDER BY email, paid_at DESC 
LIMIT 1 

べきうまく動作します。

0

カップルのオプション:

  1. LATERALサブクエリを使用してください。これはネストされたループ結合を強制することに注意してください。
  2. 最新のIPアドレスを取得して呼び出す関数を作成します。また、ネストされたループを強制します。
  3. ウィンドウ関数とそのフィルタを使用します。あなたが参加する前にテーブル全体をスキャンする必要があるので、これは通常悪化します。あなたのケースでは

、理由は労働組合の、私はおそらく第二を行うと、このような何かをするだろう:

CREATE OR REPLACE FUNCTION latest_ip(in_email text) 
RETURNS inet LANGUAGE SQL AS 
$$ 
SELECT paid_at, string_agg(browser_ip::varchar, ',') as ips 
WHERE email = in_email 
GROUP BY paid_at 
ORDER BY paid_at DESC 
LIMIT 1 
$$; 

次に、あなただけの他のあなたの列リストに

latest_ip(orders.email)を呼ぶだろうあなたの共用体の両方のブランチでLATERAL文の後にサブクエリとして上記を複製する必要があります。それについて知る価値はあるが、この場合メンテナンス上の問題があるかもしれない。

関連する問題