Increase amount in % SQL - sql

select sr.id,sr.increasedamount,sr.newsalary
from revision sr
inner join vwemp vw on vw.id=sr.id
id increasedamount newsalary
15691 14600 80000
12500 2236 26000
12501 1969 25500
1252 1982 25000
Now in this I want % to display how much % increase like in first record amount is 14600
so I want to display 14% increase in new column
id increasedamount newsalary increment in %
15691 14600 80000
12500 2236 26000
12501 1969 25500
1252 1982 25000

select sr.id,sr.increasedamount,sr.newsalary,
CASE WHEN sr.newsalary-sr.increasedamount=0 THEN 0
ELSE (sr.increasedamount)*(100/CONVERT(decimal,(sr.newsalary-sr.increasedamount))) END as 'incrementinpercentage'
from revision sr
inner join vwemp vw on vw.id=sr.id

If you need to get an amount that is 22% high then your existing amount, just multiply it by 1.22. If you need it rounded to a specific value, use the round function on the result to get to the desired amount of zeros. round(salary, -2) will round to the nearest hundred. For example, if old_salary is $100 for ID = 1, the below would result in 1, $122, $22
select sr.id, (OLD_SALARY*1.22) NewSALARY, (OLD_SALARY*1.22 -OLD_SALARY)Increasedamount from table
If you just want it to look like 22% in your result instead of .22, you will need to do something like
cast(Increment*100 as varchar)+ '%'

Below query will give you expected results
declare #userData TABLE(id int,increasedamount int,newsalary int)
insert into #userData values(15691,14600,80000)
insert into #userData values(12500,2236,26000)
insert into #userData values(12501,1969,25500)
insert into #userData values(1252,1982,25000)
select id,increasedamount,newsalary,(case when previousSalary > 0 then (increasedamount *100/previousSalary) else 0 end) incrementPercentage
from (select id,increasedamount,newsalary,(newsalary - increasedamount) previousSalary from #userData) as t

You may looking for this
SELECTC id,
increasedamount,
newsalary,
((increasedamount*1.0)/(newsalary-increasedamount))*100
FROM revision

Related

SQL making column with % of total

I am making a table with amount of transactions from other banks.
First row will be the total one. First column with absolute numbers, second with % of the total amount and third, last column, will be with name of the senders bank.
eg:
TRN
%
BANK
8000
100%
ALL
4000
50%
BANK1
2000
25%
BANK2
2000
25%
BANK3
I have trouble getting the % column as in my script the data are groupped already.
SELECT COUNT(*)
,'100%' as %,
,'ALL' as BANK
FROM table A
UNION ALL
SELECT COUNT(*)
,**IDK**
,BANK_ID BANK
FROM TABLE2 B
GROUP BY A.BANK_ID
ORDER BY 1 DESC
I know that there should be possibility with the over partition, but I can't figure out how.
Thanks for any tips!
Hi I think this should do the trick.
You can use the over partition with specifying anything in the brackets.
SELECT COUNT(*)
,'100%' as '%',
,'ALL' as BANK
UNION ALL
SELECT COUNT(*)
,cast(count(*)*100/count(*) over () as varchar) +'%'
,BANK_ID BANK
FROM TABLE2 B
GROUP BY B.BANK_ID
ORDER BY 1 DESC
Sample data:
create table demo (trn number, bank_id varchar2(10));
insert all
into demo values (1000, 'BANK1')
into demo values (1000, 'BANK1')
into demo values (1000, 'BANK1')
into demo values (1000, 'BANK1')
into demo values (1000, 'BANK2')
into demo values (1000, 'BANK2')
into demo values (1000, 'BANK3')
into demo values (1000, 'BANK3')
select * from dual;
Query:
select sum(trn)
, 100 * ratio_to_report(sum(trn)) over () * 2 as percent
, nvl(bank_id,'ALL') as bank
from demo
group by rollup (bank_id);
SUM(TRN) PERCENT BANK
---------- ---------- ----------
4000 50 BANK1
2000 25 BANK2
2000 25 BANK3
8000 100 ALL
group by rollup() generates a total row.
ratio_to_report() returns a value between 0 and 1, so I multiply by 100 to present it as a percentage.
The * 2 is because ratio_to_report() includes the whole column including the rollup total, so every value is halved.
I've assumed bank_id cannot be null and so a null value in the report must be the total row. If you need to distinguish between the total row and other null values, you can use grouping(bank_id) in a case expression, and it will return 1 for the total row and 0 for the rest. (You could also use this in an order by clause if you want to display the total row first.)
I am not overly familiar with Oracle syntax so the below may need some adjustments, but it should be portable enough. This is in MS SQL. Apologies for not being able to provide you a solution in the direct syntax you need. If someone is more familiar, please feel free to edit.
DECLARE #totalCount BIGINT = (SELECT Count(*) FROM table);
SELECT
#TotalCount AS [Count],
FORMAT(1, 'P') AS [%],
'ALL' AS [BANK]
--removed table here as the only derived value is the count and we already have it in #totalCount
UNION ALL
SELECT
COUNT(*) AS [Count],
FORMAT(CAST(Count(*) AS DECIMAL) / #TotalCount,'P') AS [%],
BANK_ID AS [BANK]
FROM [tableName]
GROUP BY [tableName].BANK_ID
--ORDER BY 1
I got to this solution and it works thankfully,
with alll as
(
SELECT
COUNT(*) trn
,'100%' AS prcnt
,'ALL' AS BANK_ID
FROM table
)
, bank as
(
SELECT distinct
count(1) over (partition by BANK_ID) cnt_B
,to_char(round(count(1) over (partition by BANK_ID)/count(*) over (partition by 1),3)*100) || '%' as prcnt
,BANK_ID
FROM table
)
select * from alll
UNION ALL
select * from bank
The MODEL clause could be used for this:
-- S a m p l e d a t a
WITH
tbl (BANK_ID, TRN) AS
(
Select 'Bank 1', 500 From Dual Union All
Select 'Bank 1', 3500 From Dual Union All
Select 'Bank 2', 1200 From Dual Union All
Select 'Bank 2', 800 From Dual Union All
Select 'Bank 3', 2000 From Dual
)
-- M a i n S Q L
SELECT TRN, PCT, BANK_ID
FROM ( SELECT BANK_ID "BANK_ID", Sum(TRN) "TRN"
FROM tbl
GROUP BY BANK_ID
ORDER BY BANK_ID
)
MODEL Dimension By(BANK_ID )
Measures(TRN, 0 as PCT)
RULES
( TRN['ALL'] = Sum(TRN)[BANK_ID != 'ALL'],
TRN[ANY] = Sum(TRN)[CV()],
PCT['ALL'] = 100,
PCT[ANY] = Sum(TRN)[CV()] * 100 / Sum(TRN)[BANK_ID != 'ALL']
)
ORDER BY BANK_ID
-- R e s u l t
TRN PCT BANK_ID
---------- ---------- -------
8000 100 ALL
4000 50 Bank 1
2000 25 Bank 2
2000 25 Bank 3

SQL Select value from other table based on column value as treshold

I have a SQLite query which returns a user name and how much a user spent (done by SELECT SUM() from the different table).
Name
Spent
Adam
700
Mike
400
Steve
100
I have another table which contains discount amount with corresponding treshold:
Treshold
Discount
200
5
400
10
600
15
I need to find what discount each user has (if it does at all). So results would look like this:
Name
Spent
Discount
Total
Adam
700
15
595
Mike
400
10
360
Steve
100
0
100
You need a LEFT join of your query to the 2nd table and aggregation:
SELECT t1.name, t1.Spent,
COALESCE(MAX(t2.Discount), 0) Discount,
t1.Spent * (1 - 0.01 * COALESCE(MAX(t2.Discount), 0)) Total
FROM (SELECT name, SUM(Spent) Spent FROM table1 GROUP BY name) t1
LEFT JOIN table2 t2 ON t2.Treshold <= t1.Spent
GROUP BY t1.name;
See the demo.
I am in a hurry. Sorry.
with a as (
select name, sum(spent) spe
from test1
group by name)
select a.name
, a.spe
, max(tres)
, max(disc)
, spe -spe * (0 || '.' || disc) total
from test2, a
where tres <= a.spe
DEMO

List out all the records when the results are filtered by GroupBy

My requirement is to verify whether the Total or Sum of Column2 (group by Column1) should be equal to Column3 (group by Column1) using MS Access.
With example,
Total of DebitAmount (group by AccountNumber) should be equal to BillAmount (for the same account number). i.e., Total of DebitAmount (or SUM(DebitAmount)) for AccountNumber='129610896' should be equal to 30000
likewise Total of DebitAmount (or SUM(DebitAmount)) for AccountNumber='184046309' should be equal to 19000
AccountNumber Code DebitAmount BillAmount
129610896 B2B001 25000 30000
129610896 B2B032 5000 30000
184046309 B2B001 15830 19000
184046309 B2B032 3170 19000
I have written a query as below
SELECT AccountNumber, BillAmount, iif ((Sum(DebitAmount) - BillAmount) = 0,1,0) as IsVerify
FROM Master_Table GROUP BY AccountNumber,BillAmount
AccountNumber BillAmount IsVerify
129610896 30000 1
184046309 19000 1
The result only displays the records group by account number. If I have 50 records, it displays only 20 as I group by account number.
But I want all the records to be displayed, IsVerify column should display the value '1' if the debit amount is equal to bill amount. If I include the column 'Code' in the query, it displays all the records, but the result displayed is invalid.
SELECT Code,AccountNumber, BillAmount, iif ((Sum(DebitAmount) - BillAmount) = 0,1,0) as IsVerify FROM Master_Table GROUP BY Code,AccountNumber,BillAmount
So how could I write the query to display all the records with the verification flag displayed as shown below.
AccountNumber GLCode DebitAmount BillAmount IsVerify
129610896 GLB2B001 25000 30000 1
129610896 GLB2B032 5000 30000 1
184046309 GLB2B001 15830 19000 1
184046309 GLB2B032 3170 19000 1
The tables are not displayed correctly. So please refer the link
http://answers.microsoft.com/en-us/office/forum/office_2013_release-access/list-out-all-the-records-when-the-results-are/c217b32a-b869-46ce-bb88-a0f98f21708f?tm=1405351469299
SELECT tm.*,
IIF(
(
SELECT Sum(t.DebitAmount)
FROM Master_Table t
WHERE t.AccountNumber = tm.AccountNumber
) = tm.BillAmount, 1, 0
)
as IsVerify
FROM Master_Table tm
Excuse me if there are some minor errors because i work on mysql and t-sql. But logic is correct.
You were almost there! :) Try this one:
SELECT mt.AccountNumber, mt.GLCode, mt.DebitAmount, mt.BillAmount, IIf(t1.SumOfDebitAmount - mt.BillAmount = 0,1,0) AS IsVerify
FROM Master_Table AS mt INNER JOIN
(SELECT AccountNumber, Sum(DebitAmount) AS SumOfDebitAmount
FROM Master_Table
GROUP BY AccountNumber) AS t1
ON mt.AccountNumber = t1.AccountNumber
ORDER BY mt.AccountNumber, mt.GLCode;
We get the DebitAmount totals within a derived table and then JOIN on account number. If the total of the DebitAmount minus the BillAmount is 0, then the rows which represent the DebitAmounts are verified. Note there was an issue with the statement:
IIf(t1.SumOfDebitAmount = mt.BillAmount,1,0)
It kept showing #Error. Not sure why, really, but I couldn't do it that way. Anyway, this should work for you.

MS Access query table without primary key

Claim# Total ValuationDt
1 100 1/1/12
2 550 1/1/12
1 2000 3/1/12
2 100 4/1/12
1 2100 8/1/12
3 200 8/1/12
3 250 11/1/12
Using MS Access, I need a query that returns only claims which have been valuated greater than $500 at some point in that claim's life time. In this example, the query should return
Claim# Total ValuationDt
1 100 1/1/12
2 550 1/1/12
1 2000 3/1/12
2 100 4/1/12
1 2100 8/1/12
because claim# 1 was valuated greater than $500 on 3/1/12, claim# 2 was valuated greater than $500 on 1/1/12, and claim# 3 was never valuated greater than $500.
You can use IN:
SELECT *
FROM Table1
WHERE Claim IN (SELECT Claim
FROM Table1
WHERE Total > 500)
Sql Fiddle Demo
Try this:
Select * from table where claim in (Select claim from table where total > 500)
Here table is the name of your table.
This could be the solution
SELECT distinct *
FROM YourTableName
WHERE claim# IN (SELECT DISTINCT claim#
FROM YourTableName
WHERE total > 500)
ORDER BY 3;
Optionally order by
This should work
Select DISTINCT Claim FROM yourtable Where Total > 500
EDIT:
In the case that my initial answer does not fulfill your requirements, then you can use a sub-query. A subquery is a query inside your query (nested queries). The reason we have to do it like that is because if you use something like
Select * FROM yourtable Where Total > 500
Then the result set would only be those moments where the total of the claim was higher than 500, but it would not indicate other moments where it was less or equal than 500.
Therefore, as others have stated, you use a subquery like:
SELECT *
FROM Table1
WHERE Claim IN (SELECT Claim
FROM Table1
WHERE Total > 500)
Note: see that there is a query after the IN keyword, so we have nested queries (or subquery if you prefer).
Why does it work? well, because:
SELECT Claim
FROM Table1
WHERE Total > 500
Will return every claim (only the number of the claim) in which the total was greater than 500 at some point. Therefore, this query will return 1 and 2. If you substitute that in the original query you get:
SELECT *
FROM Table1
WHERE Claim IN (1, 2)
Which will get you every column of every row with Claim numbers equal to either 1 or 2.
You can identify which [Claim#] values satisfy your condition ...
SELECT DISTINCT [Claim#]
FROM YourTable
WHERE [Total] > 500
If that was correct, use it as a subquery which you INNER JOIN to your table, to restrict the result set to only those claims.
SELECT y.[Claim#], y.[Total], y.[ValidationDt]
FROM YourTable AS y
INNER JOIN
(
SELECT DISTINCT [Claim#]
FROM YourTable
WHERE [Total] > 500
) AS sub
ON y.[Claim#] = sub.[Claim#];
Compare this approach vs. the IN() suggestions and see whether you notice any difference in execution speed.
You should be able to use
SELECT [Claim#],[Total],[ValidationDt]
FROM yourtable
WHERE [Claim#] IN (SELECT [Claim#]
FROM yourtable
WHERE Total >= 500)
Should return all values >= 500 for any ValidationDt.

SQL Server Rounding Issue Looking for Explanation

I've solved this issue but I'm just wondering why this works the way it does. I have a temporary table I am selecting from and am looking to display a a name, the number of records that match this name, and the percentage for that name of the total records. This is the way I originally had it:
SELECT name, number,
CASE WHEN number = 0 THEN 0 ELSE
convert(Numeric(10,2), number / CONVERT(decimal(5,2),SUM(number)) * 100)
END as "Percentage of Total"
FROM #names
group by name, number
The results I received were:
name number Percentage of Total
------------------------- ----------- ---------------------------------------
Test 1 0 0.00
Test 2 22 100.00
Test 3 28 100.00
When I change the query to this, the results are correct:
declare #total decimal(5,2)
select #total = SUM(number) FROM #names
SELECT name, number, convert(Numeric(10,2), number/ #total * 100) as "Percentage of Total"
FROM #names
group by name, number
Correct Results:
name number Percentage of Total
------------------------- ----------- ---------------------------------------
Test 1 22 44.00
Test 2 0 0.00
Test 3 28 56.00
Can someone explain what is going on, I would like to understand this better. Thanks!
Jon
You first query groups by number.
Since you don't have duplicates of numbers, number / SUM(number) is equivalent to the 1 / COUNT (except when the number is 0).
You second query does not group by number, it calculates total sum.
Use this instead:
SELECT name, number * 100.0 / SUM(number) OVER ()
FROM #names
When used with OVER clause, SUM becomes the analytical function rather than the aggregate one.
It does not shrink several records into one: instead, it returns the total value along with each record:
-- This is an aggregate function. It shrinks all records into one record and returns the total sum
WITH q (name, number) AS
(
SELECT 'test1', 0
UNION ALL
SELECT 'test2', 22
UNION ALL
SELECT 'test3', 28
)
SELECT SUM(number)
FROM q
--
50
-- This is an analytical function. It calcuates the total sum as well but does not shrink the records.
WITH q (name, number) AS
(
SELECT 'test1', 0
UNION ALL
SELECT 'test2', 22
UNION ALL
SELECT 'test3', 28
)
SELECT SUM(number) OVER ()
FROM q
--
50
50
50