How To Find The Sum By Sum Of Alias Column Value? - c#

Here i am trying to calculate the SUM of amount paid for Tution by particaular student in particular fiscal year and also for every month of that fiscal year.
For example in below line PaidTutionFee is calculated by SUM(Tution) AS PaidTutionFee. Now what i want is to sum PaidTutionFee column,
StudentId FYID Month PaidTutionFee
7 16 3 2855.00
7 16 4 2855.00
For this i have sum the Tution i.e SUM(Tution) AS PaidTutionFeeand group by StudentId, FYId, Month which will give the sum of Tution for every months for that fiscal year and finally to total Tution paid for entire fiscal year i have sum the alias of SUM(Tution) AS PaidTutionFee i.e SUM(PaidTutionFee) AS TotalTutionFeeInFiscalYear.
Now the problem is that i throws an error saying
Msg 207, Level 16, State 1, Line 11
Invalid column name 'PaidTutionFee'.
Below is my sql server query
SELECT StudentId,FYId, Month, SUM(Tution) AS PaidTutionFee,
SUM(PaidTutionFee) AS TotalTutionFeeInFiscalYear
FROM [dbo].[FeePaymentDetails]
WHERE FYId = 16 AND StudentId = 7
GROUP BY StudentId, FYId, Month

You can't aggregate an aggregate in the same SELECT statement. BUT... that's not really what you are after here. You want a sum of tuition when grouped by StudentID, FYid, Month AND a sum of tuition when grouped by StudentID, FYid (If I'm reading this correctly). For this you can use Window Functions:
SELECT StudentId,FYId, Month, SUM(Tution) AS PaidTutionFee
Sum(Tution) OVER (PARTITION BY SutdentID, FyID) as TotalTutionFeeInFiscalYear
FROM [dbo].[FeePaymentDetails]
WHERE FYId = 16 AND StudentId = 7
GROUP BY StudentId, FYId, Month;
Now your result set's granularity is at the StudentId, FYId, Month level, but you have one extra column that has it's values repeated for every distinct StudentId, FYId and it's value represents the sum for that higher level of granularity that you are after.

The much under appreciated rollup and grouping sets facilities of sqlserver can do this one quite easily:
SELECT StudentId,FYId, Month, SUM(Tution) AS PaidTutionFee
Sum(Tution) OVER (PARTITION BY SutdentID, FyID) as TotalTutionFeeInFiscalYear
FROM [dbo].[FeePaymentDetails]
/*WHERE FYId = 16 AND StudentId = 7*/
GROUP BY ROLLUP(StudentId, FYId, Month)
I've picked ROLLUP because i think it's easiest to understand
Sqlserver will do your grouping as you ask, down to the month level so you'll get a row for every month. Then thanks to the addition of ROLLUP you'll get a row with a NULL month and that is the sum of everything for the student/year. You'll also get a row with null month and null year that is the sum for the student, and a row of all nulls that is the grand total for all students. The effect is thus that the grouping/summing "rolls up" from most precise (student/year/month) to least precise (one sum of everything) in the order of right-to-left depending on the order of columns in the group by
I commented out your where clause to better demo the rollup effect - if you put it back in you'll get some totals lines that are no different to what you already know (because there is only one student and one year, so the total for all students will be the same as the total for the one student etc)
GROUPING SETS let you fine tune the subtotal/grandtotal effect better
If you made your group by like this:
GROUP BY GROUPING SETS((StudentId,FyId,Month),(StudentId,FyId))
You'll just get the month details (thanks to the first grouping set) and the lines where month is null (th total for the year) thanks to the second grouping set

You can use over Partition By to calculate running totals and grand totals without need of group by:
SELECT StudentId,FYId, Month, SUM(Tuition) over (partition by StudentId, FyId) AS PaidTutionFee,
SUM(Tution) over (partition by StudentId, Year(FyId)) AS TotalTutionFeeInFiscalYear
FROM [dbo].[FeePaymentDetails]
WHERE FYId = 16 AND StudentId = 7
Order BY StudentId, FYId, Month

Related

Calculate expiry date based on another column which is AccountType

I have a problem when I want to add a new column which is ExpireDate to my table (Player_Table) and calculate its value automatically based on the AccountType column, here is my scenario:
I have RegisteredDate(data type: date-time) column and AccountType(data type: nvchar(50)) for Example AccountType is equals to "3 Months" and I want to calculate ExpireDate by multiplying RigisteredDate by 3 I think it may work but I don't know how to calculate exactly.
id
Name
PlayerGender
PlayerAge
phone
RegisteredDate
AccountType
ExpireDate
1
nahro
male
20
00000
2021/3/5
3 months
??
2
poshya
female
21
7858
2021/3/15
6 months
??
And also how to implement this in C# Winform when I want to count the expired players.
Add a column to numerically store the duration until account expires
alter table Player_Table add Duration int not null default(3)
The ExpireDate column can then become a computed column
alter table Player_Table add column Expire_Date as
dateadd(mm,Duration,RegisteredDate)
Alternatively, or in addition to, you could add and Expired column and similarly use a computed column with case to display 1 if the account has expired, you can then count or sum this column.

SQL query to extract number of dates in the same month

I want to write a SQL command that selects from database the number of rows in which the date has the same year and month as this year and month.
For example: it's July 2020 now, so I want the command to extract the no. of rows in which the dates lie in July 2020.
From what I have understood on the other answers from Stackoverflow, I wrote this C# code:
cmd = new SqlCommand("SELECT COUNT(date) FROM ordertbl WHERE MONTH(date) = MONTH(GETDATE()) AND YEAR(date) = YEAR(GETDATE())", con);
dr = cmd.ExecuteReader();
dr.Read();
lblthismonth.Text = dr[0].ToString();
dr.Close();
The column with the date is called date.
It would be better not to manipulate your table data. Search a calculated range instead:
SELECT COUNT(date)
FROM ordertbl
WHERE
date >= CAST(DATEADD(DAY, 1, EOMONTH(GETDATE(),-1)) AS DATE) and
date < CAST(DATEADD(DAY, 1, EOMONTH(GETDATE())) AS DATE)
With your query, if you have a million rows, and 100,000 of them match, sqlserver must do 2 million date operations to extract the year and month from the million dates, and then 2 million comparisons comparing the extracted numbers. An index can not be used
If you work out a date range, and the column is indexed, then sqlserver can use the indexed data because it isn't being manipulated, and know which 100,000 rows to retrieve. In the case of a Count like this it doesn't even need to hit the table; it can just count the index
Typically we should always try to avoid putting a function call on the left hand side of a comparison operator in a WHERE clause

Update 2 million rows for 1 column

I have a table with approximately 2 million records. I have to loop through each record and update the effective date. I need to set the day to the first of the month for each date.
If the current date is the first of the month, then ignore.
i.e.
07/01/2018
07/21/2018 => 07/01/2018
08/11/2018 => 08/01/2018
Currently, I'm writing this as a C# program and it taking way too long.
Is there a better solution?
Just use DATEADD() and DATEDIFF() combination to get the first of the month date
UPDATE t
SET datecol = DATEADD(MONTH, DATEDIFF(MONTH, '1900-01-01', datecol), '1900-01-01')
FROM yourtable t;
It could be as simple as:
Update myTable
set myDate = DateAdd(day, 1-Day(myDate), myDate)
where day(myDate) > 1;

How to get data from the previous month result in SQL Server

I have 2 tables ms and fr.
ms contains columns pid,month, and totalsales, while fr contains pid, month, and forecast.
In both tables, each pid has 12 record based on month.
I actually want to calculate the demand where the formula is (0.3 * totalsales) + (0.7 * previous month result of forecast). The previous month result of forecast is like when the user choose pid 2 and month 2, then it will take the forecast result from month 1 as its calculation data.
I tried it already but the desired result is not returned:
select
((0.3 * totalsalesamount) + (0.7 * forecastdemand)) as demand
from
Monthlysales, forecastreorder
where
Monthlysales.P_ID = forecastreorder.Productid
and Monthlysales.P_ID = 1
and forecastreorder.Month = 2
When I execute the code above the result is based on their each forecast result. For example, when I choose pid 1, month 2, then it will take the forecast result from month 2 also. meanwhile i want it to take the forecast result from month 1 as its calculation data.
Try this to get previous month in sql
SELECT Convert(datetime, DateAdd(month, -1, Convert(date, GetDate())));
Using a similar table but with a year field, using ISNULL for no found data from previous moth, presume the previous is the month sales.
SELECT
0.3 * ms.totalsalesamount + 0.7 * ISNULL(fr.forecastdemand, ms.totalsalesamount) as demand
FROM
ms
LEFT OUTER JOIN
fr ON ms.pid = fr.pid
AND fr.month = CASE WHEN ms.month > 1 THEN ms.month - 1 ELSE 12 END
AND fr.year = CASE WHEN ms.month > 1 THEN ms.year ELSE ms.year - 1 END

Search data only day value of date

Is it possible to search a data by day or month value of a date type value in mysql and c#.net.please can any one help me?
You can use DAY and MONTH functions:
SELECT *
FROM yourtable
WHERE DAY(date_column) = 1
or
SELECT *
FROM yourtable
WHERE MONTH(date_column) = 1
have a look at MySQL date and time functions.

Categories

Resources