How to change UAD rate to CAD rate in hive table - hive

I have a hive table and The table rate is based on UAD. I want to calculate the Rate based on CAD dollar
Select (select rate from rate where currency_code = 'CAD') as c_rate , c_rate/r.rate
from rate r
Select (select rate from rate where currency_code = 'CAD') as c_rate , c_rate/r.rate
from rate r
Actual result:
cannot recognize input near '(' 'select' 'rate' in expression specification (state=42000,code=4000
Expect Result:
c_rate/rate

This can be done with a conditional aggregation using max window function.
select t.*,max(case when currency_code = 'CAD' then UAD_RATE end) over()/uad_rate
from tbl t

Related

How do you calculate percentage within window function respecting joins and boolean condition?

Sales Table
Sale_ID int
Sale_approved_date date
Store_ID int
Store Table
Store_ID int
Store_Name varchar
Store_Special boolean
I added the below code to calculate Store_Special with respect to overall store_special where the year is 2018. I can't seem to do a calculation where I need two group by to extract the condition with respect to overall where there is no condition for st.store_special = 1.
Expected Outcome: dd.store_special = 1/ dd.store_special =1 or dd.store_special = 0 (overall store_special count) ==> Group by month to see the ratio of store special = 1 / no condition/total count without condition.
SELECT Datepart(month,s.sale_approved_date) AS month,
Count(Datepart(month,s.sale_approved_date))/ (Sum((Datepart(month,s.sale_approved_date)) )
from sales s
LEFT JOIN store AS st
ON s.store_id = st.store_id
WHERE datepart(year,.sale_approved_date) = '2018'
AND dd.store_special = 1
GROUP BY datepart(month,.sale_approved_date)
ORDER BY count(*) DESC
Once you get the counts, you need to make sure to convert either the numerator or denominator to a float type (*1.0) to get the expected ratio. Otherwise, the ratios will be zero.
SELECT MONTH(S.sale_approved_date) AS Month,
COUNT(CASE WHEN ST.store_special = 1 THEN 1 END)*1.0 /COUNT(*) AS Ratio
FROM Store ST
JOIN Sales S
ON ST.Store_ID = S.Store_ID
WHERE YEAR(S.sale_approved_date) = 2018
GROUP BY MONTH(S.sale_approved_date)
ORDER BY COUNT(*) DESC

Multiply rate & Revenue based on currency

There are two tables one with Product-Name, revenue, Currency AND other with currency & rate
I need to convert the Revenue based on the rate:
Like: If Table1.Currecy = Table2.Currecy_code then revenue * rate else 'NA'
it is a long list of currencies.
could you please tell me which query will work to get this result.
FYI: I am using Athena database-dbeaver, not sure which sql that is.
You can use left join with case when expression
select Product_name,currency,
(case when rate is null then 'NA' else cast(revenue* rate as varchar2) end) revenue
from table1 left join table2 on Table1.Currecy = Table2.Currecy_code

Oracle SQL Multi Column <> Null Select

SELECT *
FROM GNGRB.LOAN
WHERE LOAN, INTRST, RATE IS NOT NULL
ORDER BY LOAN DESC;
Please identify the error in this query.
SELECT *
FROM GNGRB.LOAN
WHERE LOAN IS NOT NULL
AND INTRST IS NOT NULL
AND RATE IS NOT NULL
ORDER BY LOAN DESC;
I can see loan, interest and rate is all number data type values, you can use + as follows:
Select * from your_table t
Where loan + interest + rate is not null

Calculating average for each Reward Type

For each reward type, I am trying to calculate the average number of times rewards of that type has been included in a deposit. A constraint on it is that deposits that do not include reward type don't contribute to the average for that type instead of 0.
Below is the schema:
rewards(rewardId, rewardType, rewardValue);
deposit(depositId, depositDate, customerId);
details(depositId, rewardsId, numDeposit);
Here is my query:
select r.rewardsId, avg(dep.depositId)
from deposit dep join details det
on dep.depositId = det.depositId join rewards r
on r.rewardsId = det.rewardsId
group by r.rewardsId;
The answer I get doesn't seem right since the average is very high but when I count it manually, I get around 2 for each rewardType. Can someone point out what I'm doing wrong?
Since you want to count only deposits that do include reward type, then you can count them like this:
select t.rewardsId, avg(t.counter) from (
select
r.rewardsId,
sum(case when det.rewardsId is null then 0 else 1 end) counter
from deposit dep join details det
on dep.depositId = det.depositId join rewards r
on r.rewardsId = det.rewardsId
group by r.rewardsId, dep.depositId
) t
group by t.rewardsId
You definitely don't want the average of an id column.
That just doesn't make sense.
You may just want count(*):
select r.rewardsId, count(*) as num_rewards
from details det join
rewards r
on r.rewardsId = det.rewardsId
group by r.rewardsId;
From what I can tell, you don't need the deposit table. The deposit id is in the details.
Or, if you want rewards per deposit:
select r.rewardsId,
count(*) * 1.0 / count(distinct det.depositId) as num_rewards
from details det join
rewards r
on r.rewardsId = det.rewardsId
group by r.rewardsId;
Use nullif(dep.depositId, 0) to convert the zeros to null, which will not be accounted for in the average calculations.
Consider the following:
select avg(val) as avg_all,
avg(nullif(val, 0)) as avg_nonzero
from (values
(2), (4), (6), (0), (8), (0), (10)
) v(val)
which returns:
avg_all |avg_nonzero |
------------------|------------------|
4.2857142857142857|6.0000000000000000|
See nullif documentation

sql lowest running balance in a group

I've been trying for days to solve this problem to no solution.
I want to get the lowest running balance in a group.
Here is a sample data
The running balance is imaginary and is not part of the table.
the running balance is also computed dynamically.
the problem is I want to get the lowest running balance in a Specific month (January)
so the output should be 150 for memberid 10001 and 175 for memberid 10002 as highlighted in the image.
my desired out put should be
memberid | balance
10001 | 150
10002 | 175
Is that possible using sql query only?
PS. Using c# to compute lowest running balance is very slow since I have more than 600,000 records in my table.
I've updated the question.
The answer provided by Mihir Shah gave me the idea how solve my problem.
His answer takes to much time to process making it as slow as my computation on my c# program because his code loops on every record.
Here is my answer to get the minimum lowest value in a specific group (specific month) with a running value or running total without sacrificing a lot of performance.
with IniMonth1 as
(
select a.memberid, a.iniDeposit, a.iniWithdrawal,
(cast(a.iniDeposit as decimal(10,2)) - cast(a.iniWithdrawal as decimal(10,2))) as RunningTotal
from
(
select b.memberid, sum(b.depositamt) as iniDeposit, sum(b.withdrawalamt) as iniWithdrawal
from savings b
where trdate < '01/01/2016'
group by b.memberid
) a /*gets all the memberid, sum of deposit amount and withdrawal amt from the beginning of the savings before the specific month */
where cast(a.iniDeposit as decimal(10,2)) - cast(a.iniWithdrawal as decimal(10,2)) > 0 /*filters zero savings */
)
,DetailMonth1 as
(
select a.memberid, a.depositamt,a.withdrawalamt,
(cast(a.depositamt as decimal(10,2)) - cast(a.withdrawalamt as decimal(10,2))) as totalBal,
Row_Number() Over(Partition By a.memberid Order By a.trdate Asc) RowID
from savings a
where
a.trdate >= '01/01/2016'
and
a.trdate <= '01/31/2016'
and (a.depositamt<>0 or a.withdrawalamt<>0)
) /* gets all record within the specific month and gives a no of row as an id for the running value in the next procedure*/
,ComputedDetailMonth1 as
(
select a.memberid, min(a.runningbalance) as MinRunningBal
from
(
select a.rowid, a.memberid, a.totalbal,
(
sum(b.totalbal) +
(case
when c.runningtotal is null then 0
else c.runningtotal
end)
)as runningbalance , c.runningtotal as oldbalance
from DetailMonth1 a
inner join DetailMonth1 b
on b.rowid<=a.rowid
and a.memberid=b.memberid
left join IniMonth1 c
on a.memberid=c.memberid
group by a.rowid,a.memberid,a.totalbal,c.runningtotal
) a
group by a.memberid
) /* the loop is only for the records of the specific month only making it much faster */
/* this gets the running balance of specific month ONLY and ADD the sum total of IniMonth1 using join to get the running balance from the beginning of savings to the specific month */
/* I then get the minimum of the output using the min function*/
, OldBalanceWithNoNewSavingsMonth1 as
(
select a.memberid,a.RunningTotal
from
IniMonth1 a
left join
DetailMonth1 b
on a.memberid = b.memberid
where b.totalbal is null
)/*this gets all the savings that is not zero and has no transaction in the specific month making and this will become the default value as the lowest value if the member has no transaction in the specific month. */
,finalComputedMonth1 as
(
select a.memberid,a.runningTotal as MinRunTotal from OldBalanceWithNoNewSavingsMonth1 a
union
select b.memberid,b.MinRunningBal from ComputedDetailMonth1 b
)/*the record with minimum running total with clients that has a transaction in the specific month Unions with the members with no current transaction in the specific month*/
select * from finalComputedMonth1 order by memberid /* display the final output */
I have more than 600k savings record on my savings table
Surprisingly the performance of this code is very efficient.
It takes almost 2hr using my c# program to manually compute every record of all the members.
This code makes only 2 secs and at most 9 secs just to compute everything.
i Just display to c# for another 2secs.
The output of this code was tested and compared with my computation using my c# program.
May be below one is help you
Set Nocount On;
Declare #CashFlow Table
(
savingsid Varchar(50)
,memberid Int
,trdate Date
,deposit Decimal(18,2)
,withdrawal Decimal(18,2)
)
Insert Into #CashFlow(savingsid,memberid,trdate,deposit,withdrawal) Values
('10001-0002',10001,'01/01/2015',1000,0)
,('10001-0003',10001,'01/07/2015',25,0)
,('10001-0004',10001,'01/13/2015',25,0)
,('10001-0005',10001,'01/19/2015',0,900)
,('10001-0006',10001,'01/25/2015',25,0)
,('10001-0007',10001,'01/31/2015',25,0)
,('10001-0008',10001,'02/06/2015',25,0)
,('10001-0009',10001,'02/12/2015',25,0)
,('10001-0010',10001,'02/18/2015',0,200)
,('10002-0001',10002,'01/01/2015',500,0)
,('10002-0002',10002,'01/07/2015',25,0)
,('10002-0003',10002,'01/13/2015',0,200)
,('10002-0004',10002,'01/19/2015',25,0)
,('10002-0005',10002,'01/25/2015',25,0)
,('10002-0006',10002,'01/31/2015',0,200)
,('10002-0007',10002,'02/06/2015',25,0)
,('10002-0008',10002,'02/12/2015',25,0)
,('10002-0009',10002,'02/12/2015',0,200)
;With TrialBalance As
(
Select Row_Number() Over(Partition By cf.memberid Order By cf.trdate Asc) RowNum
,cf.memberid
,cf.deposit
,cf.withdrawal
,cf.trdate
From #CashFlow As cf
)
,RunningBalance As
(
Select tb.RowNum
,tb.memberid
,tb.deposit
,tb.withdrawal
,tb.trdate
From TrialBalance As tb
Where tb.RowNum = 1
Union All
Select tb.RowNum
,rb.memberid
,Cast((rb.deposit + tb.deposit - tb.withdrawal) As Decimal(18,2))
,rb.withdrawal
,tb.trdate
From TrialBalance As tb
Join RunningBalance As rb On tb.RowNum = (rb.Rownum + 1) And tb.memberid = rb.memberid
)
Select rb.memberid
,Min(rb.deposit) As runningBalance
From RunningBalance As rb
Where Year(rb.trdate) = 2015
And Month(rb.trdate) = 1
Group By rb.memberid