SQL query result issue - sql

The query is used to get balance of certain client
SELECT t.[InvoiceID], t.S_Type as Type,
t.Date, t.Debit, t.Credit, b.Balance
FROM Statement as t CROSS apply
(SELECT Balance = SUM(Debit) - SUM(Credit)
FROM Statement as x
WHERE (x.date < t.date or
x.date = t.date
) AND
x.InvoiceID = t.InvoiceID
AND x.CustID = t.CustID
) b
WHERE t.CustID ='2' and date between '2015-01-01' and '2016-01-12'
order by InvoiceID, Type desc, Date
out out i get
InvoiceID Type Date Debit Credit Balance
4 Sales Invoice 2015-06-09 520.00 0.00 520.00
4 Receipt Voucher 2016-01-04 0.00 520.00 0.00
6 Sales Invoice 2015-06-09 160.00 0.00 160.00
6 Receipt Voucher 2016-01-04 0.00 160.00 0.00
9 Sales Invoice 2015-06-09 850.00 0.00 850.00
9 Receipt Voucher 2016-01-04 0.00 850.00 0.00
13 Sales Invoice 2015-06-09 200.00 0.00 200.00
20 Sales Invoice 2015-07-11 1225.00 0.00 1225.00
176 Sales Invoice 2015-12-14 900.00 0.00 900.00
the issue is with with sales invoices # 13 20 176 its supposed to sum the debit of invoice and show in balance
so right out put should be like this
InvoiceID Type Date Debit Credit Balance
4 Sales Invoice 2015-06-09 520.00 0.00 520.00
4 Receipt Voucher 2016-01-04 0.00 520.00 0.00
6 Sales Invoice 2015-06-09 160.00 0.00 160.00
6 Receipt Voucher 2016-01-04 0.00 160.00 0.00
9 Sales Invoice 2015-06-09 850.00 0.00 850.00
9 Receipt Voucher 2016-01-04 0.00 850.00 0.00
13 Sales Invoice 2015-06-09 200.00 0.00 200.00
20 Sales Invoice 2015-07-11 1225.00 0.00 1425.00
176 Sales Invoice 2015-12-14 900.00 0.00 2325.00

I think the logic is slightly off in the subquery.
SELECT t.[InvoiceID], t.S_Type as Type,
t.Date, t.Debit, t.Credit, b.Balance
FROM Statement as t CROSS apply
(SELECT Balance = SUM(Debit) - SUM(Credit)
FROM Statement as x
WHERE x.CustID = t.CustID AND
(x.date < t.date or
x.date = t.date AND x.InvoiceID <= t.InvoiceID
)
) b
WHERE t.CustID ='2' and
date between '2015-01-01' and '2016-01-12'
ORDER BY InvoiceID, Type desc, Date;
In other words, the prioritization for the cumulative sum should be date first and then when the dates are the same, use the invoice.
This means that all your values are really being miscalculated, because each invoice is starting over (with your original logic). However, the earlier invoices are fully paid, so you don't see the issue with them.
Note: in more recent versions of SQL Server, this is much easier (and more efficient) with the cumulative sum syntax:
sum(debit - credit) over (partition by custid order by date, invoiceid)
Or, if debit and credit could take on NULL values:
sum(coalesce(debit, 0) - coalesce(credit, 0)) over (partition by custid order by date, invoiceid)

Related

I want to update values of a null column using the values of other column in SELECT statement

I have a select statement with multiple joins I also have a blank column in SQL statement I want to update the value of this NULL column which I created with the values of another column which is also in the same select statement.
I tried update statement but it did not work.
SELECT
null as loan_group
,[Loan Number] as loan_number
,[DateofNote] as open_data
,[lnamount] as original_note_amount
,[EOM Balance] as current_principal_balance
,b.status
FROM
tblbordata2 B
INNER JOIN tblLOANDATA2 L ON B.[Student ID] = L.[Student ID]
INNER JOIN tblLoanStatus LS ON LS.[Status ID] = B.Status
INNER JOIN SCHOOLS S ON S.SchoolNumber = b.SchoolNumber
INNER JOIN [School Types] ST ON ST.[School Type ID] = S.SchoolID
loan_group loan_number open_data original_note_amount current_principal_balance status
NULL 1566 1997-10-14 00:00:00.000 6495.00 0.00 6
NULL 1564 1997-10-13 00:00:00.000 6495.00 0.00 4
NULL 1577 1997-10-17 00:00:00.000 2895.00 0.00 9
NULL 1557 1997-10-11 00:00:00.000 2875.00 0.00 6
NULL 1558 1997-10-14 00:00:00.000 3845.00 0.00 19
NULL 1561 1997-10-10 00:00:00.000 1995.00 0.00 19
NULL 1553 1997-10-13 00:00:00.000 3500.00 0.00 6
NULL 1548 1997-10-09 00:00:00.000 3645.00 0.00 19
NULL 1555 1997-10-13 00:00:00.000 2000.00 0.00 4
NULL 1582 1997-10-23 00:00:00.000 4500.00 0.00 19
NULL 1575 1997-10-18 00:00:00.000 3945.00 0.00 4
NULL 1574 1997-10-16 00:00:00.000 4600.00 0.00 19
NULL 1560 1997-10-15 00:00:00.000 3736.00 0.00 4
NULL 1594 1997-10-20 00:00:00.000 2500.00 0.00 6
NULL 1593 1997-10-28 00:00:00.000 3000.00 0.00 4
NULL 1591 1997-10-24 00:00:00.000 3862.00 0.00 6
NULL 1590 1997-10-23 00:00:00.000 6495.00 0.00 6
NULL 1586 1997-10-13 00:00:00.000 3395.00 0.00 6
NULL 1588 1997-10-18 00:00:00.000 3495.00 0.00 4
NULL 1587 1997-10-18 00:00:00.000 3495.00 0.00 6
I want to replace the first column loan group such that if the status is 6 or 4 "R" else "P"
Use CASE with IN clause
SELECT
case when status IN
('6' , '4' )
then 'R'
else 'P'
end as loan_group
,[Loan Number] as loan_number
,[DateofNote] as open_data
,[lnamount] as original_note_amount
,[EOM Balance] as current_principal_balance
,b.status
FROM
tblbordata2 B
INNER JOIN tblLOANDATA2 L ON B.
[Student ID] = L.[Student ID]
INNER JOIN tblLoanStatus LS ON LS.
[Status ID] = B.Status
INNER JOIN SCHOOLS S ON
S.SchoolNumber = b.SchoolNumber
INNER JOIN [School Types] ST ON ST.
[School Type ID] = S.SchoolID
Put this in the code for the column you are trying to insert:
SELECT
case when loan_group is null then
case when status = 6 or status = 4 then 'R'
else 'P'
end
end
,[Loan Number] as loan_number
,[DateofNote] as open_data
,[lnamount] as original_note_amount
,[EOM Balance] as current_principal_balance
,b.status

Obtaining payment dates of debit using credit payment dates and aggregates in SQL - slow query

Edit2: CTE was the reason for the slow query. Problem solved.
Edit: Instead of updating, I'm going to create another column of payment date. The following code works perfectly however it is incredibly slow. Is there any other method to do this faster?
WITH sum_data AS (SELECT CustomerID
, ISSUEDATE
, DEBIT
, CREDIT
, SUM(DEBIT) over(PARTITION BY CustomerID
ORDER BY ISSUEDATE
ROWS UNBOUNDED PRECEDING) SUM_DEBIT
, SUM(CREDIT) over(PARTITION BY CustomerID
ORDER BY ISSUEDATE
ROWS UNBOUNDED PRECEDING) SUM_CREDIT
FROM Test_Table)
SELECT d.CustomerID
, d.ISSUEDATE
, d.DEBIT
, d.CREDIT
, (SELECT MIN(ISSUEDATE)
FROM sum_data d2
WHERE d2.SUM_CREDIT >= d.SUM_DEBIT
AND d2.CustomerID = d.CustomerID) PAYMENTDATE
FROM sum_data d
WHERE DEBIT != 0
Pre-Edit: I have a dataset that shows transaction information for different customers. Credit lines have issue date and payment date the same because they are issued and paid at the same time. However for the debit lines payment date will be when that debit is cleared by the credit. So starting from the bottom, we have 4 debit before a credit is entered. 1398.83 credit clears the amount of 1336.13 debit so I want to update the last row with the payment date of 9/20/2018. 2672 of credit above it covers the second to last row of 1398.83 so that row's payment date should be 9/22/2018. Remaining balance of (1398.83-1336.13) + (2672 - 1398.83) does not cover the remaining debits so we will keep on checking if new credit rows cover the debit amounts and will start clearing debits (as in updating payment date) from the last entry and when the debit is cleared we will update the payment date with the clearing credit row's payment date as in the above examples. This will be done for all different customer IDs (partition by).
CustomerID ISSUEDATE DEBIT CREDIT
M00008 4/2/2019 1345.53 0
M00008 3/19/2019 0 1336.13
M00008 3/18/2019 0 1403.4
M00008 3/4/2019 1406.13 0
M00008 3/4/2019 1336.13 0
M00008 2/28/2019 0 1336.13
M00008 2/21/2019 0 1399.19
M00008 2/4/2019 1403.4 0
M00008 2/4/2019 1336.13 0
M00008 1/28/2019 0 1513
M00008 1/22/2019 0 1337.94
M00008 1/4/2019 1398.83 0
M00008 1/4/2019 1336.13 0
M00008 12/3/2018 1513.03 0
M00008 12/3/2018 1336.13 0
M00008 11/19/2018 0 2958
M00008 11/19/2018 0 2908.25
M00008 11/5/2018 1461.56 0
M00008 11/2/2018 1367.92 0
M00008 10/20/2018 0 1336.13
M00008 10/19/2018 0 1398.83
M00008 10/3/2018 1489.94 0
M00008 10/2/2018 1541.03 0
M00008 9/22/2018 0 2672
M00008 9/20/2018 0 1398.83
M00008 9/3/2018 1398.83 0
M00008 9/3/2018 1336.13 0
M00008 8/3/2018 1398.83 0
M00008 8/2/2018 1336.13 0
Output from query above on this dataset:
CustomerID ISSUEDATE DEBIT CREDIT PAYMENTDATE
M00008 2018-08-02 1336.13 0.00 2018-09-20
M00008 2018-08-03 1398.83 0.00 2018-09-22
M00008 2018-09-03 1398.83 0.00 2018-10-19
M00008 2018-09-03 1336.13 0.00 2018-10-20
M00008 2018-10-02 1541.03 0.00 2018-11-19
M00008 2018-10-03 1489.94 0.00 2018-11-19
M00008 2018-11-02 1367.92 0.00 2018-11-19
M00008 2018-11-05 1461.56 0.00 2018-11-19
M00008 2018-12-03 1513.03 0.00 2019-01-22
M00008 2018-12-03 1336.13 0.00 2019-01-28
M00008 2019-01-04 1398.83 0.00 2019-02-21
M00008 2019-01-04 1336.13 0.00 2019-02-21
M00008 2019-02-04 1403.40 0.00 2019-03-18
M00008 2019-02-04 1336.13 0.00 2019-03-18
M00008 2019-03-04 1406.13 0.00 NULL
M00008 2019-03-04 1336.13 0.00 NULL
M00008 2019-04-02 1345.53 0.00 NULL
Using select within select statement will always have effect on performance. For your query, using CROSS APPLY should yield the results faster.
WITH sum_data AS (SELECT CustomerID
, ISSUEDATE
, DEBIT
, CREDIT
, SUM(DEBIT) over(PARTITION BY CustomerID
ORDER BY ISSUEDATE
ROWS UNBOUNDED PRECEDING) SUM_DEBIT
, SUM(CREDIT) over(PARTITION BY CustomerID
ORDER BY ISSUEDATE
ROWS UNBOUNDED PRECEDING) SUM_CREDIT
FROM Test_Table)
SELECT d.CustomerID
, d.ISSUEDATE
, d.DEBIT
, d.CREDIT
, PaymentDate
FROM sum_data d
CROSS APPLY (SELECT MIN(ISSUEDATE) AS PaymentDate
FROM sum_data d2
WHERE d2.SUM_CREDIT >= d.SUM_DEBIT
AND d2.CustomerID = d.CustomerID) t
WHERE DEBIT != 0

getting debit cedit and balance issue

I am using the below query to the following information from table statement
SELECT [Statement_ID] as SID, t.[InvoiceID], t.S_Type as Type,
t.Description, t.Date, t.Debit, t.Credit, b.Balance
FROM Statement as t CROSS apply
(SELECT Balance = SUM(Debit) - SUM(Credit)
FROM Statement as x
WHERE (x.date < t.date or
x.date = t.date and x.[Statement_ID] <= t.[Statement_ID]
) AND
x.CustID = t.CustID
) b
WHERE t.CustID ='48' and date between '2015-01-01' and '2016-01-01'
ORDER BY t.date
out put
SID InvoiceID Type Date Debit Credit Balance
176 51 Service Invoice 2015-08-29 500.00 0.00 500.00
462 51 Receipt Voucher 2015-09-07 0.00 500.00 0.00
107 76 Service Invoice 2015-09-28 1000.00 0.00 1000.00
165 208 Service Invoice 2015-09-28 500.00 0.00 1500.00
217 119 Service Invoice 2015-10-31 500.00 0.00 2000.00
459 76 Receipt Voucher 2015-11-21 0.00 500.00 1500.00
460 208 Receipt Voucher 2015-11-21 0.00 500.00 1000.00
461 119 Receipt Voucher 2015-11-21 0.00 500.00 500.00
163 165 Service Invoice 2015-12-01 500.00 0.00 1000.00
458 165 Receipt Voucher 2015-12-22 0.00 500.00 500.00
44 224 Service Invoice 2015-12-31 500.00 0.00 1000.00
First how can i get each Receipt Voucher under it invoice
second when i have Receipt Voucher with same date of invoice how i can be sure it gets under Invoice using Statement_ID since Receipt Voucher is always entered after the invoice
the expected out put
order invoices by date and get it Receipt Voucher
S_ID InvoiceID Type Date Debit Credit Balance
176 51 Service Invoice 2015-08-29 500.00 0.00 500.00
462 51 Receipt Voucher 2015-09-07 0.00 500.00 0.00
107 76 Service Invoice 2015-09-28 1000.00 0.00 1000.00
459 76 Receipt Voucher 2015-11-21 0.00 500.00 500.00
165 208 Service Invoice 2015-09-28 500.00 0.00 1000.00
460 208 Receipt Voucher 2015-11-21 0.00 500.00 500.00
217 119 Service Invoice 2015-10-31 500.00 0.00 1000.00
461 119 Receipt Voucher 2015-11-21 0.00 500.00 500.00
163 165 Service Invoice 2015-12-01 500.00 0.00 1000.00
458 165 Receipt Voucher 2015-12-22 0.00 500.00 500.00
44 224 Service Invoice 2015-12-31 500.00 0.00 1000.00
This this...
With CTE1 AS
(
SELECT [Statement_ID] as SID, t.[InvoiceID], t.S_Type as Type,
t.Description, t.Date, t.Debit, t.Credit, b.Balance
FROM Statement as t CROSS apply
(SELECT Balance = SUM(Debit) - SUM(Credit)
FROM Statement as x
WHERE (x.date < t.date or
x.date = t.date and x.[Statement_ID] <= t.[Statement_ID]
) AND
x.CustID = t.CustID
) b
WHERE t.CustID ='48' and date between '2015-01-01' and '2016-01-01'
), CTE2 AS
(
SELECT Row_Number() Over (Order By [Date]) As priorityID,
[InvoiceID]
FROM CTE1
WHERE [Type] = 'Service Invoice'
)
Select c1.*
From CTE1 c1
JOIN CTE2 c2
ON c1.[InvoiceID] = c2.[InvoiceID]
ORDER BY c2.priorityID, c1.[Date]

Adding values from different records

From the below table I want to add 2 values from the same records and one value from different record, that are (extraaamt from the first record)+(trnamt from the second record)
5140560000001183 1016.00 0.00 2014-05-23 R 0.00 1017 13
5140560000001183 1016.00 0.00 2014-05-24 N 30.00 1017 0
carno emi recamt lastrecdate status penamt trnamt extraamt
5140560000001183 1016.00 0.00 2014-05-23 R 0.00 1017 13
5140560000001191 880.00 0.00 2014-05-23 R 0.00 880 0
5140560000001142 934.00 0.00 2014-05-23 P 0.00 500 0
5140560000001209 963.00 0.00 2014-05-23 P 0.00 600 0
5140560000001175 1024.00 0.00 2014-05-23 N 0.00 0 0
5140560000001167 1117.00 0.00 2014-05-23 N 0.00 0 0
5140560000001159 834.00 0.00 2014-05-23 N 0.00 0 0
5140560000001183 1016.00 0.00 2014-05-24 N 30.00 1017 0
5140560000001191 880.00 0.00 2014-05-24 N 0.00 880 0
5140560000001142 934.00 0.00 2014-05-24 N 0.00 500 0
5140560000001209 963.00 0.00 2014-05-24 N 0.00 600 0
5140560000001175 1024.00 0.00 2014-05-24 N 0.00 0 0
5140560000001167 1117.00 0.00 2014-05-24 N 0.00 0 0
5140560000001159 834.00 0.00 2014-05-24 N 0.00 0 0
I have used the below query but still it is not helping:
Select
Case WHEN ( lastrecdate=( cast (GETDATE() as DATE))and CardNo=CardNo and Status in('N','P') ) then trnammt else 0 end +
Case WHEN ( lastrecdate=( cast (GETDATE() as DATE))and CardNo=CardNo and Status in('N','P')) then pendamt else 0 end +
Case WHEN (lastrecdate= (select MAX(lastrecdate ) from Tbl_Emi WHERE Status ='R' and CardNo=CardNo) ) then extraamt else 0 end as totalamount
from Tbl_Emi where CardNo=CardNo
Please google on CrossTab query/Pivot Query. You can achieve this task using this.
CrossTab query is amazing, which helps generating reports and play with aggregate values. Excel/Ms Access gives nice user interface for Pivot Table. It’s way to transfer rows into column. It is more often used to generate matrix form of report.
Look at this blog.
select tt.carno, t1.extraamt+t2.trnamt total from
(select t.carno,
MIN(t.lastrecdate) first
, MAX(t.lastrecdate) second
from dbo.[Table] t
group by t.carno) tt
inner join dbo.[Table] t1
on t1.carno=tt.carno and t1.lastrecdate=tt.first
inner join dbo.[Table] t2
on t2.carno=tt.carno and t2.lastrecdate=tt.second

Simple SQL math operation gives incorrect results

I am running into an issue with a simple SQL math operation of qty * price is returning an incorrect value.
This is SQL server 2005. Compatibility is set to 80 for 2000 SQL server.
Any help on understanding why I am having the problem shown below
For example:
Transaction Table:
id price qty
1 2.77 20.00
1 2.77 25.00
1 2.77 10.00
2 0.10 50.00
2 0.10 80.00
3 0.10 50.00
3 0.10 60.00
SQL
Select id, price, qty, (qty * price) from transact
The actual problem was this and it was my fault :(
Select id, CAST(price AS DECIMAL(5,2)), qty, (qty * price) from transact
Returns the following:
id price qty Total
1 2.77 20.00 55.400000 Correct
1 2.77 25.00 69.250000 Correct
1 2.77 10.00 27.700000 Correct
2 0.10 50.00 4.800000 Should be 5.0000
2 0.10 80.00 7.680000 Should be 8.0000
2 0.10 50.00 5.050000 Should be 5.0000
2 0.10 60.00 6.060000 Should be 6.0000
3 39.00 1.00 39.000000 Correct
3 39.00 2.00 78.000000 Correct
3 39.00 3.00 117.000000 Correct
You price is being rounded somewhere. The select you are running is not showing the actual price.
select round(0.096, 2) price, 0.096 * 50.00 total
Result:
price total
0.10 4.80000