Derived/calculated column on existing table - sql

I have been going nuts over this issue for some time and I am seeking help.
I have SQL Server table with values, as follows:
Account - Date - Amount - Summary
10000 - 2010-1-1 - 50.00 - 0.00
10000 - 2010-2-1 - 50.00 - 0.00
10000 - 2010-3-1 - 50.00 - 0.00
10000 - 2010-4-1 - 50.00 - 0.00
10000 - 2010-5-1 - 50.00 - 0.00
10000 - 2010-6-1 - 50.00 - 0.00
10000 - 2010-7-1 - 50.00 - 0.00
10000 - 2010-8-1 - 50.00 - 0.00
10000 - 2010-9-1 - 50.00 - 0.00
10000 - 2010-10-1 - 50.00 - 0.00
10000 - 2010-11-1 - 50.00 - 0.00
10000 - 2010-12-1 - 50.00 - 600.00
10000 - 2011-1-1 - 25.00 - 0.00
10000 - 2011-2-1 - 25.00 - 0.00
10000 - 2011-3-1 - 50.00 - 0.00
10000 - 2011-4-1 - 50.00 - 0.00
10000 - 2011-5-1 - 50.00 - 0.00
10000 - 2011-12-1 - 25.00 - 825.00
10000 - 2012-1-1 - 100.00 - 0.00
10000 - 2012-2-1 - 200.00 - 0.00
10000 - 2012-3-1 - 100.00 - 0.00
10000 - 2012-5-1 - 100.00 - 0.00
10000 - 2012-6-1 - 100.00 - 0.00
10000 - 2012-8-1 - 100.00 - 0.00
10000 - 2012-12-1 - 100.00 - 1625.00
10001 - 2010-1-1 - 50.00 - 0.00
10001 - 2010-2-1 - 60.00 - 0.00
10001 - 2010-12-1 - 60.00 - 170.00
10001 - 2011-1-1 - 50.00 - 0.00
10001 - 2011-2-1 - 50.00 - 0.00
10001 - 2011-3-1 - 50.00 - 0.00
10001 - 2011-4-1 - 50.00 - 0.00
10001 - 2011-6-1 - 50.00 - 0.00
10001 - 2011-8-1 - 50.00 - 0.00
10001 - 2011-10-1 - 50.00 - 0.00
10001 - 2011-12-1 - 50.00 - 570.00
This is a basic snapshot of the table. The "Summary" column gives the total for the "Amounts" at the end of the year (based on "date" column), but only when the MONTH(Date) = '12'. It goes on this way for hundreds of accounts, with about 4 more years as well. I would like to add a column to this existing table, called "SummaryPreviousYear". The SummaryPreviousYear column should have the sum of the amounts from MONTH(Date) = '12' and the previous year. I'd like to join this column on the account number, so that it sits next to the Summary column and gives a value just like the Summary value does, but the SummaryPreviousYear value would need to be present the whole way down the column, not just where the month is 12. For example, the following row:
Before:
Account - Date - Amount - Summary
10001 - 2011-10-1 - 50.00 - 0.00
10001 - 2011-12-1 - 50.00 - 570.00
After:
Account - Date - Amount - Summary - SummaryPreviousYear
10001 - 2011-10-1 - 50.00 - 0.00 - 170.00
10001 - 2011-12-1 - 50.00 - 570.00 - 170.00
Can anyone help me with this? I am pulling my hair out here for 2 days and need to get this dataset created so I can proceed with my report development. Unfortunately, the DBA's off site. Literally at my wit's end. Any help would be greatly appreciated.

Why are you duplicating this summary and previous year summary data for each row in your database? This is wasteful and unnecessary. It would be far better to have another table with previous year summaries, one row per year, that you could join to this table. And, I don't see a need for a Summary column at all. Why not create a view that calculates a Summary, when the month is 12, and returns a zero for any month not equal to 12.

SELECT l.*,
q.summary AS SummaryPreviousYear
FROM lists l
LEFT JOIN
(
SELECT Date,
Summary
FROM lists
WHERE MONTH(Date) = 12
) AS q
ON YEAR(l.Date) = YEAR(q.Date) + 1

SELECT
t.Account,
t.Date,
t.Amount,
t.Summary,
s.Summary as SummaryPreviousYear
FROM TestTable t
JOIN (
SELECT
Account,
DATEPART(YEAR, Date) as Year,
SUM(Amount) as Summary
FROM TestTable
GROUP BY Account, DATEPART(YEAR, Date)
) s
ON s.Account = t.Account
AND s.Year = DATEPART(YEAR, Date) - 1

Related

SQLServer - Pivoting a table with Group

I am wondering if what I am trying to do is possible. I believe it is using the PIVOT function in TSQL but don't have enough experience with the PIVOT function to know where to start.
Basically I'm trying to take the following # table called #tmpbudgetdata (truncated for simplicity):
Account Description BudgetAmount Period
-------------------- ---------------------------------------------------------------------------------------------------- --------------------- --------------------
4001 Mood Embedded Account 0.00 1
4001 Mood Embedded Account 0.00 2
4001 Mood Embedded Account 0.00 3
4001 Mood Embedded Account 0.00 4
4001 Mood Embedded Account 0.00 5
4001 Mood Embedded Account 0.00 6
4001 Mood Embedded Account 0.00 7
4001 Mood Embedded Account 0.00 8
4001 Mood Embedded Account 0.00 9
4001 Mood Embedded Account 0.00 10
4001 Mood Embedded Account 0.00 11
4001 Mood Embedded Account 0.00 12
4003 DBS Music 0.00 1
4003 DBS Music 0.00 2
4003 DBS Music 0.00 3
4003 DBS Music 0.00 4
4003 DBS Music 0.00 5
4003 DBS Music 0.00 6
4003 DBS Music 0.00 7
4003 DBS Music 0.00 8
4003 DBS Music 0.00 9
4003 DBS Music 0.00 10
4003 DBS Music 0.00 11
4003 DBS Music 0.00 12
4010 Sales - Software 5040.00 1
4010 Sales - Software 0.00 2
4010 Sales - Software 6280.56 3
4010 Sales - Software 6947.93 4
4010 Sales - Software 4800.00 5
4010 Sales - Software 0.00 6
4010 Sales - Software 2400.00 7
4010 Sales - Software 2550.00 8
4010 Sales - Software 4800.00 9
4010 Sales - Software 2400.00 10
4010 Sales - Software 0.00 11
4010 Sales - Software 2400.00 12
4015 New Install Revenue 0.00 1
4015 New Install Revenue 0.00 2
4015 New Install Revenue 0.00 3
4015 New Install Revenue 3844.79 4
4015 New Install Revenue 0.00 5
4015 New Install Revenue 0.00 6
4015 New Install Revenue 0.00 7
4015 New Install Revenue 0.00 8
4015 New Install Revenue 0.00 9
4015 New Install Revenue 0.00 10
4015 New Install Revenue 0.00 11
4015 New Install Revenue 0.00 12
and turning it into something like this:
Account Description Period1 Period2 Period3 Period4 Period5 Period6 Period7 Period8 Period9 Period10 Period11 Period12
------- --------------- -------- ------- -------- ------ ------- ------- -------- ------ ------- -------- -------- --------
4001 Mood Enabled... 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
4003 Dbs Music 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
4010 Sales - Software 5040.00 0.00 6280.56 6947.93 4800.00 0.00 2400.00 2550.00 4800.00 2400.00 0.00 2400.00
...etc...
Basically just grouping via the Account column (the description is the same per account) and then taking the period values and pivoting them horizontally.
I know I could do it with a cursor and loop through but wondering if this is possible with a pivot or by other means.
Thanks in advance
I simple PIVOT should do the trick
Example
Select *
From (
Select [Account]
,[Description]
,Period = concat('Period',Period)
,[BudgetAmount]
From YourTable
) src
Pivot (sum([BudgetAmount]) for Period in ( [Period1],[Period2],[Period3],[Period4],[Period5],[Period6],[Period7],[Period8],[Period9],[Period10],[Period11],[Period12] ) ) pvt
Returns

How would I add both these rows together in one row with the sum of both rows

594517 2018-11-30 5.00 0.00 0.00 0.00 8.00
594517 2018-12-18 0.00 0.00 0.00 0.00 5.00
Thanks all for the reply my situation if very hard to explain with out showing the code im dealing with,Basically the fix to a huge problem would be to get many rows with different dates into one row also adding all the totals for all those row into that same one row
column is the ID, date, the rest are total for services
I have created a table called KingLove which looks like this to try out something similar to what you're explaining on my own computer:
ID date service1 service2 service3 service4 service5
----------- ---------- --------- --------- --------- --------- ---------
594517 2018-11-30 5.00 0.00 0.00 0.00 8.00
594517 2018-12-18 0.00 0.00 0.00 0.00 5.00
If I then run this query:
select max(date) as [date], sum(service1) + sum(service2) + sum(service3) + sum(service4) + sum(service5) as [sum]
from KingLove
I get the service columns summed up and the latest date as the date for the entire row. Like this:
date sum
---------- --------
2018-12-18 18.00
You could swap the max in the query for a min if you want the oldest date instead.
It is not very easy to understand what your desired outcome would be, but I hope this is what your asking.

SQL query result issue

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)

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