2016-09-26 51 views
1

我有一個派生表中包含列:找出第一個記錄是一定值以上

  • 電子郵件(主標識符)
  • transaction_time

如何看待對於PostgreSQL中的第一個事務,基於amount > 500的客戶(通過電子郵件標識)?

注意:這用於用於過濾主表的子查詢。

+2

您可以添加示例數據和預期結果。 –

回答

0

這也許應該這樣做:

SELECT DISTINCT ON (email) * 
FROM t 
WHERE amount > 500 
ORDER BY email, transaction_time 

它將返回第一筆交易(相對於transaction_time)爲每封電子郵件。

+3

馬特,請看看DISTINCT ON。 –

2

下面的解決方案將更便攜,DISTINCT ON這是Postgres特定的。使用row_number()枚舉行,並得到所有不同的客戶(通過電子郵件標識)有他們的第一筆交易金額大於500

編輯:我已經包括三種方式來達到同樣的效果。選擇你喜歡的任何一個。

第一種方法 - 使用row_number()

select 
    distinct email 
from (
    select 
    email, 
    amount, 
    row_number() OVER (PARTITION BY email ORDER BY transaction_time) AS rn 
    from <derived_table_here> 
) t 
where 
    rn = 1 
    and amount > 500 

第二條本辦法 - 使用DISTINCT ON

select 
    email 
from (
    select distinct on (email) 
    email, 
    amount 
    from <derived_table_here> 
    order by email, transaction_time 
) t 
where amount > 500 

第三種方法 - 使用NOT EXISTS

select 
    email 
from <derived_table_here> t1 
where 
    amount > 500 
    and not exists(
    select 1 
    from <derived_table_here> t2 
    where 
     t1.email = t2.email 
     and t1.transaction_time > t2.transaction_time 
    ) 

我發現第三種方法最便攜,因爲MySQL實例不支持窗口函數AFAIK。這僅僅是在將來在數據庫之間切換的情況下 - 對你來說更少的工作。


測試下面樣品:

 email  |  transaction_time  | amount 
-----------------+----------------------------+-------- 
[email protected] | 2016-09-26 19:01:15.297251 | 400 -- 1st, amount < 500 
[email protected] | 2016-09-26 19:01:19.160095 | 500 
[email protected] | 2016-09-26 19:01:21.526307 | 550 
[email protected] | 2016-09-26 19:01:28.659847 | 600 -- 1st, amount > 500 
[email protected] | 2016-09-26 19:01:30.292691 | 200 
[email protected] | 2016-09-26 19:01:31.748649 | 300 
[email protected] | 2016-09-26 19:01:38.59275 | 200 -- 1st, amount < 500 
[email protected] | 2016-09-26 19:01:40.833897 | 100 
[email protected] | 2016-09-26 19:01:51.593279 | 501 -- 1st, amount > 500 
+0

根據我的理解,適用where條款可能會取消第一筆交易的資格,而我們不能在第一筆交易中取消第一筆交易的資格,不管這筆交易在開始時是多少,而是將其標記爲第一筆交易。 –

+0

@Matt其實我已經測試過了,你錯了。 –

+0

是的,我錯過了你最初在做什麼,並以不同的方式解釋它。但在1個查詢中仍然有更好的方法 – Matt

0

另一種選擇:

select * from t t1 
where amount > 500 
and not exists 
(select 1 from t t2 where t1.email=t2.email and t1.transaction_time>t2.transaction_time) 
0

LEFT SELF連接方法

SELECT t1.* 
    FROM 
     ExmapleTable t1 
     LEFT JOIN ExmapleTable t2 
     ON t1.Email = t2.Email 
     AND t2.transaction_time < t1.transaction_time 
    WHERE 
     t1.Amount >= 500 
     AND t2.Email IS NULL 
    ; 

http://rextester.com/XRQTX2627

相關問題