I have a table where customer transactions are stored in this format:
Account Tran_type Tran_Amount tran_particular Tran_date
165266 C 5000 deposit 19_SEP-2014
165266 D 3000 withdrawal 20-SEP-2014
165266 C 8000 Deposit 21-SEP-2014
I am attempting to extract the Information for a Statement like this:
select tran_date, tran_particular,
(case when tran_type = 'C' then tran_amt else 0 end) CREDIT,
(case when tran_type = 'D' then tran_amt else 0 end) DEBIT
from tran_table order bby tran_date asc;
Is there a wat to add the Balance column on each row so it would show the Balance after the Transaction? say:
DATE DESC CREDIT DEBIT BALANCE
19-SEP-2014 DEPOSIT 5000 0 5000
20-SEP-2014 WITHDRAWAL 3000 2000
21-SEP-2014 DEPOSIT 8000 0 10000
Please assist.
EDIT I have trie the aswers suggested but it seems my balance is tagged to the date. See the output I have currently:
See the Balance does not change until the date changes.
select tran_date, tran_particular, Credit, Debit,
SUM(Delta) OVER (ORDER BY tran_date) AS Balance
from
(
select tran_date, tran_particular,
Case Tran_Type
When 'C' THEN Tran_Amount
Else 0
End AS Credit,
Case Tran_Type
When 'D' THEN Tran_Amount
Else 0
End AS Debit,
Case Tran_Type
When 'C' THEN Tran_Amount
When 'D' THEN -1 * Tran_Amount
Else 0
End AS Delta
from TRANSACTIONS
order by tran_date
)
Should do it
Select *,Sum( case when type ='C'
then amount
else -amount
end ) over (ORDER BY date ROWS
BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )'Balance'
from #tt1
That will cost a sub-query:
SELECT tran_date, tran_particular,
(CASE when tran_type = 'C' THEN tran_amt ELSE 0 end) CREDIT,
(CASE when tran_type = 'D' THEN tran_amt ELSE 0 end) DEBIT,
(SELECT
SUM(CASE when type = 'C' tran_amt ELSE (-1) * tran_amt end)
FROM tran_table trn2
WHERE
trn2.Account = trn1.Account
AND trn2.tran_id <= trn1.tran_id
-- AND trn2.tran_date <= trn1.tran_date
)
BALANCE
FROM
tran_table trn1 ORDER BY tran_date asc;
In large scale data, having such a sub-query is not recommended. Having a materialized view is more rational.
Related
account
DR_DESCRIPTION
CR_DESCRIPTION
DR_AMOUNT
CR_AMOUNT
xxx-111-xxx
land
60
xxx-111-xxx
cash
21300
xxx-111-xxx
capital
1789
xxx-111-xxx
diesel
480
xxx-111-xxx
gas
19687
xxx-111-xxx
food
1193
xxx-111-xxx
water
1789
xxx-111-xxx
electricity
0
I have the following result set of a query
However, what I would like to do is remove the nulls and make the results look like this:
account
DR_DESCRIPTION
CR_DESCRIPTION
DR_AMOUNT
CR_AMOUNT
xxx-111-xxx
land
diesel
60
480
xxx-111-xxx
cash
gas
21300
19687
xxx-111-xxx
capital
food
1789
1193
xxx-111-xxx
water
1789
xxx-111-xxx
electricity
0
The query I am using is:
SELECT account,
CASE WHEN debit_credit = 'DR' THEN DESCRIPTION END dr_description,
CASE WHEN debit_credit = 'CR' THEN DESCRIPTION END cr_description,
SUM(CASE WHEN debit_credit = 'DR' THEN income_amount END) DR_AMOUNT,
SUM(CASE WHEN debit_credit = 'CR' THEN income_amount END) CR_amount
FROM xxxxx
GROUP BY account, CASE WHEN debit_credit = 'DR' THEN DESCRIPTION END,
CASE WHEN debit_credit = 'CR' THEN DESCRIPTION END
I think you just need to fix your current query:
select account,
max(case when debit_credit = 'DR' then DESCRIPTION end) as dr_description,
max(case when debit_credit = 'CR' then DESCRIPTION end) as cr_description,
sum(case when debit_credit = 'DR' then income_amount end) as DR_AMOUNT,
sum(case when debit_credit = 'CR' then income_amount end) as CR_amount
from xxxxx
group by account;
The above returns one row per account. If you want each debit and credit individually, then you would use row_number(). Assuming you have a column that specifies the ordering:
select account,
max(case when debit_credit = 'DR' then DESCRIPTION end) as dr_description,
max(case when debit_credit = 'CR' then DESCRIPTION end) as cr_description,
sum(case when debit_credit = 'DR' then income_amount end) as DR_AMOUNT,
sum(case when debit_credit = 'CR' then income_amount end) as CR_amount
from (select x.*,
row_number() over (partition by account, debit_credit order by <ordering column>) as seqnum
from xxxxx x
) x
group by account, seqnum;
I have a table in MS SQL DB which contains transactions of any company, there are two columns
sub_cat_code
total_amount
The total_amount contain sometimes positive and sometimes negative value. Where positive values indicates the sale and negative value indicates Returns.
Now, I need to find the percentage of sales and percentage of return using following query, in percentage of return column every value coming same. any help would be appreciable.
Select prod_subcat_code ,
(sum(total_amt)*100 /(select sum(total_amt) from transection)) as
Sale_pers,
((select sum(total_amt) from transection where total_amt<0)*100/(select
sum(total_amt) from transection)) as return_sale
from transection
group by prod_subcat_code
order by Sale_pers desc
Use a CTE which returns the total sales and total returns of the table:
with cte as (
select
sum(case when total_amount > 0 then total_amount else 0 end) total_sales,
sum(case when total_amount < 0 then total_amount else 0 end) total_returns
from transection
)
select prod_subcat_code ,
100.0 * sum(case when total_amount > 0 then total_amount else 0 end) / (select total_sales from cte) as sale_perc,
100.0 * sum(case when total_amount < 0 then total_amount else 0 end) / (select total_returns from cte) as return_perc
from transection
group by prod_subcat_code
See the demo.
If I understand correctly, you just want to divide two aggregated values:
Select prod_subcat_code,
sum(total_amt) as net_sales,
sum(case when total_amt > 0 then total_amt else 0 end) as sales,
sum(case when total_amt < 0 then total_amt else 0 end) as returns,
(sum(case when total_amt > 0 then total_amt else 0 end) /
nullif(sum(total_amt), 0)
) as sales_ratio,
(sum(case when total_amt < 0 then total_amt else 0 end) /
nullif(sum(total_amt), 0)
) as return_ratio
from transection
group by prod_subcat_code;
You may want change your query to this for desired result:
Select prod_subcat_code,
sum(case when total_amt > 0 then total_amt else 0 end) as sales,
(sum(case when total_amt > 0 then total_amt else 0 end) /
(sum(total_amt)) ) * 100 as sales_Percent,
sum(case when total_amt < 0 then total_amt else 0 end) as [returns],
(sum(case when total_amt < 0 then total_amt else 0 end) /
(sum(total_amt)) ) * 100 as Return_Percent
from transection
group by prod_subcat_code
order by sales_Percent desc
Hope it will help you,
SELECT prod_subcat_code
,(SUM(CASE WHEN total_amt > 0 THEN total_amt END)/sum(total_amt))*100 AS Sales_Percentage
,(SUM(CASE WHEN total_amt < 0 THEN total_amt END)/sum(total_amt))*100 AS Return_Percentage
FROM transection
GROUP BY prod_subcat_code;
I have a Claim table that holds the claim amount. I need to write a query to compare if the amount is the same or not.
SELECT
CLAIM_NO, SUM(TRAN_AMOUNT) AS Amount
FROM
CLMTABLE
WHERE
TRTYPE = 0
GROUP BY
CLAIM_NO
UNION ALL
SELECT
CLAIM_NO, SUM(TRAN_AMOUNT) AS Amount
FROM
CLMTABLE
WHERE
TRTYPE <> 0
GROUP BY
CLAIM_NO
OUTPUT
CLAIM_NO AMOUNT
-----------------
1234567890 883.00
1234567890 883.00
1234567891 990.00
1234567891 990.00
1234567892 883.00
1234567892 893.00
The last record the amount is not the same, i want to be able to spot the claim that the amount doesn't match.
Thanks, any help will be appreciated
Please use below query to find all such transaction:
SELECT CLAIM_NO,SUM(CASE WHEN TRTYPE=0 THEN ISNULL(TRAN_AMOUNT,0) ELSE 0 END) As Amount,
SUM(CASE WHEN TRTYPE<>0 THEN ISNULL(TRAN_AMOUNT,0) ELSE 0 END) AS Amount2
FROM CLMTABLE
GROUP BY CLAIM_NO
HAVING SUM(CASE WHEN TRTYPE=0 THEN ISNULL(TRAN_AMOUNT,0) ELSE 0 END) <> SUM(CASE WHEN TRTYPE<>0 THEN ISNULL(TRAN_AMOUNT,0) ELSE 0 END)
Use a CASE inside a SUM func to retrieve the difference between amount of different types.
SELECT claim_no, SUM(CASE WHEN trtype = 0 THEN tran_amount
ELSE -1*tran_amount
END) as delta
FROM clmtable
GROUP BY claim_no
I have this SQL query
SELECT COUNT(*)*100/(SELECT COUNT(*) FROM tickets WHERE status = 'closed')
FROM tickets
WHERE closed_at <= due_at
UNION
SELECT COUNT(*)*100/(SELECT COUNT(*) FROM tickets WHERE status = 'closed')
FROM tickets
WHERE closed_at > due_at;
and it returns this
ROW 1 - 35
ROW 2 - 47
but I need the return like this:
1 | 2 |
35 47
I need the returns in columns, not rows.
Thanks.
Use conditional aggregation. I would recommend:
SELECT (SUM(CASE WHEN closed_at <= due_at THEN 100.0 ELSE 0 END) /
SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END)
),
(SUM(CASE WHEN closed_at > due_at THEN 100.0 ELSE 0 END) /
SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END)
)
FROM tickets ;
It seems strange that you are filtering on status = 'closed' in the denominator, but not in the numerator. If status = closed should be the filter for both, then you can simplify this to:
SELECT AVG(CASE WHEN closed_at <= due_at THEN 100.0 ELSE 0 END),
AVG(CASE WHEN closed_at > due_at THEN 100.0 ELSE 0 END)
FROM tickets
WHERE status = 'closed';
select account
, SUM(balance) as bal
from Main_report
Group BY account
How can I separate the positive and negative records from the above query?
I want to combine this query with the cases listed below.
select (case when bal < 0 then bal else 0 end) as debits,
(case when bal > 0 then bal else 0 end) as credits from Main_report
Group BY account
Just use your two cases and sum the result of those:
SELECT account
, SUM(CASE WHEN balance < 0 THEN balance ELSE 0 END) as debits
, SUM(CASE WHEN balance > 0 THEN balance ELSE 0 END) as credits
FROM Main_report
GROUP BY account