2017-03-10 65 views
0

我基本上是(postgre)SQL的新手,必須爲以下方案編寫一個查詢。我敢打賭,這裏對更有經驗的成員來說幾乎是可笑的,但請耐心等待(我現在甚至沒有數據庫來測試它)。具有多個條件的「複雜」查詢(BEGINNER)

一個查詢,以顯示爲每個用戶(類型= A): 最後正(全成) 「請求」(REQUEST_ID,CREATION_DATE,量), 「量」 的 總和所有的失敗 「請求」, 積極對否定要求的比例。

給定兩個表: USER_ACCOUNT - 包含用戶列的獨特帳戶:ACCOUNT_ID(類型:INT8,鍵列,IS_NULLABLE:否),CREATION_DATE(類型:時間戳),ACCOUNT_TYPE(類型:VARCHAR,可能的值:{a,b})
請求 - 包含每個請求:request_id(int8,key列,IS_NULLABLE:NO)creation_date(timestamp),account_id(int8),amount(float8),type(type:varchar ,可能值{positiv,是負面})

所以我的理解是,我可以把兩個表一起機智小時連接語句,如:

SELECT request.request_id, 
request.creation_date, request.amount 
From user_account 
INNER JOIN request ON (user_account.account_id = request.account_id) 
Where request.type = POSITIV AND account_type = a; 
SELECT sum(request.amount) as failed_amount 
From user_account 
INNER JOIN request ON (user_account.account_id = request.account_id) 
Where request.type = NEGATIV AND account_type = a;    
  1. 假如這是正確的,我怎麼將它們合併成一個查詢? (我讀到子查詢,並把第二個SELECT語句的WHERE子句中?)
  2. 對於我猜的比例,我都數不過來()的積極和消極的要求和他們分開,但老實說,我不知道如何在這種情況下執行它。

如果有人能給我一個簡短的演練,我會非常高興和感激。

+0

可能不會解決所有問題,請注意,您所做的連接意味着您獲得了所有請求(添加了有關相應用戶的列和數據),而不僅僅是最後的請求。我會首先找到每個用戶最後一次請求的日期 - 「SELECT account_id,MAX(timestamp)FROM request GROUP BY account_id' –

回答

0

TL;博士在最後的代碼塊應該給你想你想,有一些細微的變化,使其在postgre工作

使用子查詢是一個比較中間的話題,所以不要泄氣如果你沒有得到它。我會在幾個步驟中通過它。

(1)組成的一些試驗數據和連接表

(2)選擇最近期Positiv請求

(3)是負面的量的SELECT SUM

(4)選擇的positiv比到是負面的計數


測試數據和參考

對於這個答案,我將使用下表作爲測試數據:

#user_account 
+ ---------- + ------------- + ------------ + 
| account_id | creation_date | account_type | 
+ ---------- + ------------- + ------------ + 
| 1   | 2016-02-14 | B   | 
| 2   | 2016-02-14 | A   | 
| 3   | 2016-04-06 | B   | 
| 4   | 2016-04-29 | B   | 
| 5   | 2016-09-03 | A   | 
+ ---------- + ------------- + ------------ + 

#request 
+ ---------- + ------------- + ---------- + ------- + ------------ + 
| request_id | creation_date | account_id | amount | request_type | 
+ ---------- + ------------- + ---------- + ------- + ------------ + 
| 1   | 2016-03-08 | 1   | 4308.02 | positiv  | 
| 2   | 2016-04-08 | 1   | 1718.56 | negativ  | 
| 3   | 2016-03-11 | 2   | 911.50 | positiv  | 
| 4   | 2016-03-12 | 2   | 38.42 | negativ  | 
| 5   | 2016-03-12 | 2   | 110.12 | positiv  | 
| 6   | 2016-05-08 | 3   | 1843.19 | positiv  | 
| 7   | 2016-09-12 | 4   | 7234.11 | negativ  | 
| 8   | 2016-10-12 | 4   | 515.51 | negativ  | 
| 9   | 2016-10-12 | 5   | 0.01 | positiv  | 
| 10   | 2016-10-18 | 5   | 13.02 | positiv  | 
+ ---------- + ------------- + ---------- + ------- + ------------ + 

我將使用table aliasing,我已經改名申請表的類型字段request_type。哦,還有一兩件事:這是寫在SQL Server中,但它應該postgre工作,只有輕微的修改:)

開始簡單的,讓我們的表連接在一起,並在ACCOUNT_TYPE

select * 
    from #user_account u 
    inner join #request r on r.account_id = u.account_id 
    where u.account_type = 'A' 

濾除給出了下面的表,我將作爲參考

+ ---------- + ------------- + ------------ + ---------- + ------------- + ------ + ------------ + 
| account_id | creation_date | account_type | request_id | creation_date | amount | request_type | 
+ ---------- + ------------- + ------------ + ---------- + ------------- + ------ + ------------ + 
| 2   | 2016-02-14 | A   | 3   | 2016-03-11 | 911.5 | positiv  | 
| 2   | 2016-02-14 | A   | 4   | 2016-03-12 | 38.42 | negativ  | 
| 2   | 2016-02-14 | A   | 5   | 2016-03-12 | 110.12 | positiv  | 
| 5   | 2016-09-03 | A   | 9   | 2016-10-12 | 0.01 | positiv  | 
| 5   | 2016-09-03 | A   | 10   | 2016-10-18 | 13.02 | positiv  | 
+ ---------- + ------------- + ------------ + ---------- + ------------- + ------ + ------------ + 


選擇申請

使用

爲了理解相關的子查詢,我們假設我有上面的表格和一個變量@account_id = 2。通過查看參考表,我們可以看到,對於帳戶2,我們希望選擇reference_id 5,因爲它是最近的正式請求。下面的查詢讓我們只是

select top 1 request_id 
    from #request 
    where account_id = @account_id 
     and request_type = 'positiv' 
     order by creation_date desc 

要在我們的查詢使用這個想法,我們需要用u.account_id更換@account_id,像這樣

select u.account_id 
     , r.request_id 
     , r.creation_date 
     , r.amount 
    from #user_account u 
    inner join #request r on r.account_id = u.account_id 
    where u.account_type = 'A' 
     and r.request_id = (
      select top 1 request_id 
       from #request 
       where account_id = u.account_id -- correlate to the reference table 
        and request_type = 'positiv' 
       order by creation_date desc 
     ) 

這讓我們把它變成一個相關子查詢正是我們想要

+ ---------- + ---------- + ------------- + ------ + 
| account_id | request_id | creation_date | amount | 
+ ---------- + ---------- + ------------- + ------ + 
| 2   | 5   | 2016-03-12 | 110.12 | 
| 5   | 10   | 2016-10-18 | 13.02 | 
+ ---------- + ---------- + ------------- + ------ + 


選擇是負面的總和金額

我們將在後面兩部分中使用相關子查詢的相同概念,但在這裏我們將它們放在語句的選擇部分,因爲我們不再需要過濾掉任何結果。該查詢

select u.account_id 
     , r.request_id 
     , r.creation_date 
     , r.amount 
     , (select isnull(SUM(amount),0) -- replaces a null value with 0 
       from #request 
        where account_id = u.account_id 
        and request_type = 'negativ') as SumOfFailed 
    from ... -- same as above 

給我們

+ ---------- + ---------- + ------------- + ------ + ----------- + 
| account_id | request_id | creation_date | amount | SumOfFailed | 
+ ---------- + ---------- + ------------- + ------ + ----------- + 
| 2   | 5   | 2016-03-12 | 110.12 | 38.42  | 
| 5   | 10   | 2016-10-18 | 13.02 | 0   | 
+ ---------- + ---------- + ------------- + ------ + ----------- + 


選擇比

我們基本上做同樣的事情在這裏,但它可能很容易迷失在鑄造和除零檢查。所以希望我把它拆分成夠線,它清楚地

select u.account_id 
     , r.request_id 
     , r.creation_date 
     , r.amount 
     , (...) as SumOfFailed -- same as above 
     , cast((-- convert integer to float 
      select COUNT(*) 
       from #request 
       where account_id = u.account_id 
        and request_type = 'positiv' 
      ) as float) 
      /nullif(-- if divisor is zero, return null 
      CAST((
       select COUNT(*) 
        from #request 
        where account_id = u.account_id 
         and request_type = 'negativ' 
      ) as float), 0) as Ratio 
    from ... -- same as above 

這讓我們

+ ---------- + ---------- + ------------- + ------ + ----------- + ----- + 
| account_id | request_id | creation_date | amount | SumOfFailed | Ratio | 
+ ---------- + ---------- + ------------- + ------ + ----------- + ----- + 
| 2   | 5   | 2016-03-12 | 110.12 | 38.42  | 2  | 
| 5   | 10   | 2016-10-18 | 13.02 | 0   | Null | 
+ ---------- + ---------- + ------------- + ------ + ----------- + ----- + 


代碼塊

因此,所有一起,你將SQL語句是這樣的,有一些小的差異,使其在Postgre中工作。

select u.account_id 
     , request_id 
     , r.creation_date 
     , r.amount 
     , (select isnull(SUM(amount),0) -- replaces a null value with 0 
       from #request 
        where account_id = u.account_id 
         and request_type = 'negativ') as SumOfFailed 
     , cast((
      select COUNT(*) 
       from #request 
       where account_id = u.account_id 
        and request_type = 'positiv' 
      ) as float) 
      /nullif(
      CAST((
       select COUNT(*) 
        from #request 
         where account_id = u.account_id 
          and request_type = 'negativ' 
      ) as float),0) as Ratio 
    from #user_account u 
    inner join #request r on r.account_id = u.account_id 
    where u.account_type = 'A' 
     and r.request_id = (
      select top 1 request_id 
       from #request r_sq 
       where r_sq.account_id = u.account_id 
        and r_sq.request_type = 'positiv' 
       order by creation_date desc 
     ) 

希望這有助於!

+0

這裏幫助的意願數量是INSANE。非常感謝你,一切都如你所描述的那樣。對於postgresql,我只是使用「限制1」而不是「top 1」和「coalesce」而不是「isnull」。令人敬畏的演練,11/10會再次問。 – fairlynew

+0

不客氣:)很高興我能幫上忙。 – KindaTechy