我基本上对(postgre)SQL很新,并且必须为以下场景编写一个查询。我敢打赌,对于经验丰富的会员来说,这几乎是可笑的,但请耐心等待我(我现在甚至没有数据库来测试它)。
为每个用户显示一个查询(type = a): 最后一个积极的(成功的)"请求" (request_id,creation_date,amount), 总和"金额"所有失败的"请求", 正面和负面请求的比率。
给出两个表:
user_account - 包含用户列的唯一帐户:account_id(类型:int8,键列,IS_NULLABLE:NO),creation_date(类型:timestamp),account_type(类型:varchar,可能值:{a, b})
请求 - 包含每个请求:request_id(int8,key列,IS_NULLABLE:NO)creation_date(timestamp),account_id(int8),amount(float8),type(类型:varchar,可能值{positiv,否定})
所以我理解的是我可以将两个表与join语句结合在一起,如:
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;
如果有人能给我一个简短的演练,我会非常高兴和感激。
答案 0 :(得分:0)
tl; dr 最后的代码块应该给你想要的东西,稍加一些改动,使它在postgre中工作
使用子查询是一个更中间的主题,因此如果您没有获得它,请不要气馁。我将在几个步骤中引导您完成它。
(1)组成一些测试数据并连接表
(2)选择最近的积极请求
(3)选择Negativ金额总和
(4)选择积极与否定的比率
测试数据和参考
对于这个答案,我将使用下表作为测试数据:
#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,因为它是最新的positiv请求。以下查询为我们提供了
select top 1 request_id
from #request
where account_id = @account_id
and request_type = 'positiv'
order by creation_date desc
要在我们的查询中使用此提示,我们需要将@account_id
替换为u.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 |
+ ---------- + ---------- + ------------- + ------ +
选择Negativ金额的总和
我们将在接下来的两个部分中使用相同子查询的相同概念,但是在这里我们将它们放在我们语句的选择部分中,因为我们不再需要过滤掉任何结果。此查询
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
)
希望这有帮助!