Match month of outer query to month in subquery - sql

I am attempting to get the total of a column (Amount) by Month:
SELECT
Date,
DATEPART(month, Date) AS Month,
DATEPART(year, Date) AS year,
(
SELECT
SUM(Amount)
FROM Transactions AS T
WHERE DATEPART(month, Date) = DATEPART(month, T.Date)
) AS Amount
FROM Transactions AS T
I know that this could be done in a straightforward manner using a group by clause as follows:
SELECT
DATEPART(month, Date) AS Month,
SUM(Amount) AS Total
FROM Transactions AS T
GROUP BY DATEPART(month, Date)
However I need to use subquery instead as the subquery will contain additional conditions and joins to assist in the calculation of a total based on rules from other tables.
I expected the first query to return all months and their respective totals, in the subquery I am matching Month of the transactions with the Month of the outer query row. However it simply returns the full SUM of all months for each month.
My guess is that my attempt to match the month is not quite correct, but I can't see how to fix.

Related

Attempting to combine results from two queries

I have two queries:
select
CM.Month,
CM.Year
FROM CalendarMonths AS CM
The above query returns all montts and years from available in a Calendar Table.
The second query is as follows:
select
DATEPART(month, T.Date) AS Month,
DATEPART(year, T.Date) AS Year,
ISNULL(SUM(Amount) ,0) As Total
from Transactions T
inner join TransactionClasses TC on TC.TransactionClassId = T.TransactionClassId AND T.TransactionClassId = 3
GROUP BY
DATEPART(month, T.Date),
DATEPART(year, T.Date)
This simply returns the the total for Transactions that belong to a specific Transaction Class grouped by month and year. The above query only returns rows for months and years which actually contain transactions.
What I am attempting to accomplish is combining both queries, so that as well returning totals for month and year which contains Transactions, it also returns zero total for the rest of the months.
My attempts so far have been unsuccesfull so any help would be appreciated.
You need to LEFT JOIN to your data set. I would put your second query into a CTE/derived table, and that makes the JOINing easier:
WITH Totals AS(
SELECT DATEPART(MONTH, T.Date) AS Month,
DATEPART(YEAR, T.Date) AS Year,
SUM(TC.Amount) AS Total
FROM dbo.Transactions T
INNER JOIN dbo.TransactionClasses TC ON TC.TransactionClassId = T.TransactionClassId
WHERE T.TransactionClassId = 3 --Moved from ON
GROUP BY DATEPART(MONTH, T.Date),
DATEPART(YEAR, T.Date))
SELECT CM.Month,
CM.Year,
ISNULL(T.Total,0) AS Total
FROM dbo.CalendarMonths CM
LEFT JOIN Totals T ON CM.Month = T.Month
AND CM.Year = T.Year;

How to query months and group them in SQL Server

I have a query which sums up the transactions of a given month over a given period in SQL Server. I want to list the months and transactions in a table but the DATENAME() function is only returning one month i.e January in the list. The query is as shown below ..
SELECT
DATENAME(MONTH, DATEPART(MONTH FROM TransactionDate)) AS Month_Name,
SUM(ABS(Income)) AS Income
FROM
Transactions
GROUP BY
DATEPART(MONTH FROM TransactionDate)
Please help ...
Try this,
SELECT
datename(mm,TransactionDate) AS Month_Name,
SUM(ABS(Income)) AS Income
FROM Transactions
GROUP BY
datename(mm, TransactionDate)
Try this:
select datename(mm, TransactionDate) month_name, sum(income) income
from transactions
group by month_name
Remove some unnecessary to tune up the performance.

Group by clause query with derived fields

My table has quantity, sale price and sale date, and I need to derive the sales price and group the sales by month. I used the below but wasn't able to get the group by clause right.
select
(QUANTITY*SALEPRICE) as sales,
DATEPART (month, saledate) as MM
from [dbo].[PETSALE]
GROUP BY DATEPART (month, saledate)
You would need an aggregate function in the select clause to make your statement a valid aggregate query.
I would phrase your query as:
select
sum(quantity * saleprice) as sales, -- aggregate function
year(saledate) yyyy,
month(saledate) mm
from [dbo].[petsale]
group by year(saledate), month(saledate)
Note that I added the sales year to the select and group by clauses: in case your data spreads over more than 12 months, you probably don't want sales from the same month in different years to be grouped together. But if you do, you can just remove year(saledate) from the query.

Simple sql query, but stuck on it

database mode
The only relevant table is 'employee' in the database model.
Asked: In which month are the most employee's birthdays?
By using
SELECT DATEPART(m, dateofbirth) AS month
FROM employee
I can actually see all the months for every employee and count it myself.
But how can I show the most common birthday month?
Thanks in advance!
recent output (for comment below)
You need to use GROUP BY. This groups up the separate month values. Once you've done that, you can apply COUNT, and then order the values in descending order on that statistic. Then you need to wrap that logic in a Common Table Expression, so you can select just the months that have the maximum COUNT.
WITH ranking AS (
SELECT
DATEPART(m, dateofbirth) AS month,
COUNT(*) as ct
FROM DM_MTA.dbo.employee
GROUP BY DATEPART(m, dateofbirth)
)
select
month
from
ranking
where ct = (select max(ct) from ranking)
This would give you exact month you're looking for:
SELECT TOP 1 DATEPART(m, dateofbirth) AS month
FROM employee
GROUP BY DATEPART(m, dateofbirth)
ORDER BY count(DATEPART(m, dateofbirth)) DESC

Grouping all dates as one field and showing the sum of sales

I have converted all dates within my table to reflect as YYYY/MM/01 but I am left with 25 or so of these dates that are all the same and I just want to group them together and I can't figure out how to do it. I'm newish to SQL and was hoping someone could point me in the right direction for this.
Much appreciated!
SELECT
DATEFROMPARTS(YEAR(ReportedDate), MONTH(ReportedDate), 1) AS Date, SUM(Sales) Sales
FROM
dbo.Sales
WHERE
YEAR(ReportedDate) = 2018 AND MONTH(ReportedDate) = 01
GROUP BY
ReportedDate
Because you are grouping by ReportedDate, for every ReportedDate you will get a record, even though you didn't select ReportedDate in your SELECT clause. Think of it as a hidden column in your data. Instead, try grouping by the functions in your select statement.
SELECT
DATEFROMPARTS(YEAR(ReportedDate), MONTH(ReportedDate), 1) AS Date, SUM(Sales) Sales
FROM
dbo.Sales
WHERE
YEAR(ReportedDate) = 2018 AND MONTH(ReportedDate) = 01
GROUP BY
DATEFROMPARTS(YEAR(ReportedDate), MONTH(ReportedDate), 1)
As an alternative to your query I suggest you to use EOMONTH function. You would not need to use extra date functions. And I think it's better to show last day of month than first day when showing totals per month
SELECT
EOMONTH(ReportedDate) AS Date, SUM(Sales) Sales
FROM
dbo.Sales
WHERE
EOMONTH(ReportedDate) = EOMONTH(GETDATE(), -1)
GROUP BY
EOMONTH(ReportedDate)
Notes:
EOMONTH(GETDATE(), -1) gets last day of previous month
Use DATEADD(DD, 1, EOMONTH(ReportedDate, -1)) to get first day of month