SQl query to sum-up amounts by month/year - sql-server

I have a table "TABLE" like this:
Date(datatime)
Paid(int)
I have multiple "Paid" amounts per month.
I would like to sum up the Paid amount per month/year.
So far this is what I tried but I get errors in EXTRACT and in MONTH and however I am far to get it done with the years.
SELECT
EXTRACT(MONTH FROM Period) AS reference_month
, SUM(Paid) AS monthly_payments
FROM Paid
GROUP BY EXTRACT(MONTH FROM Period)
ORDER BY EXTRACT(MONTH FROM Period)
I am not really handy at this and I would really appreciate some help.

select year(date) as y, month(date) as m, sum(paid) as p
from table
group by year(date), month(date)

SELECT YEAR([Date]) AS [Year], MONTH([Date]) AS [Month], SUM(Paid) AS Total
FROM TABLE_NAME
GROUP BY YEAR([Date]), MONTH([Date])
You need to use square brackets around your objects name [] when you have named your object with sql server key words.

Related

AdventureWorks in SQL Server 2019 : ordershare percent for each item per month

I'm new to SQL Server. I'm trying to write a code to find the sale percent/per item/per month. Something like this:
Year
Month
ProductID
Order_Quantity_Per_Month
Total_Sold_Per_Month
%_Of_Total_Sale
2011
5
707
422
17024
2
First and most importantly, I want to write this code with "CTE" and "Group by". I've tried many times but I failed. How can I write this code with cte and group by?
I wrote this code with "Over" and "Partition". Could someone check the codes I've written to see if it's actually correct:
USE AdventureWorks2019
GO
SELECT
YEAR (soh.OrderDate) As Year,
MONTH (soh.OrderDate) As Month,
pro.productid AS [Product ID],
pro.Name AS [Product Name],
SUM(sod.OrderQty) OVER (PARTITION BY Month(soh.OrderDate) ORDER BY by soh.OrderDate) AS [Order Quantity Per Month],
SUM(sod.OrderQty) OVER (PARTITION BY Month(soh.OrderDate)) AS [Total Sold Per Month],
SUM(sod.OrderQty) OVER (PARTITION BY Month(soh.OrderDate) ORDER BY by soh.OrderDate) * 100 / SUM(sod.OrderQty) OVER (PARTITION BY Month(soh.OrderDate)) AS [% of TotalSale]
FROM
Production.Product pro
INNER JOIN
Sales.SalesOrderdetail sod ON pro.ProductID = sod.ProductID
INNER JOIN
Sales.SalesOrderheader soh ON soh.SalesOrderID = sod.SalesOrderID
GROUP BY
YEAR(soh.OrderDate), MONTH(soh.OrderDate),
soh.OrderDate, pro.productid, pro.Name, sod.OrderQty
ORDER BY
Year, Month
If the above code is correct, How can I write the code with cte and group by?
I think the better question is why you want (or need) to use a CTE. A simple CTE (i.e., not recursive) is just syntactic sugar for a derived table. There is nothing particular special or complicated about writing and using one in a query. If you "tried many times", you should have included those attempts in your question.
But to satisfy the need to use a CTE, you can simply "cram" the query you have into the CTE and select rows from it. Example:
with cteOrders as (
select ... -- your original query here without ORDER BY clause
)
select * from cteOrders
order by [Year], [Month]
;
That is a extremely simplistic way of using a CTE. There is no real or obvious advantage to doing so but it does satisfy your goal. Because of that, I smell a XY problem.

Make a summary report in SQL Server

I'm working on this database that I want it to create a summary sum(Amount) report on the all the tables that will be specified. I tried this but it didn't get what I expected.
SELECT SUM(Amount) AS Expenditure
FROM Expenditure
WHERE Amount IS NOT NULL
UNION ALL
SELECT SUM(Amount)
FROM auxiliary
WHERE Category IS NOT NULL AND Amount >0;
This only shows
and this is want to achieve:
How do I make that possible?
SELECT 'Expenditure' AS TableName, SUM(Amount) AS Amount
FROM Expenditure
WHERE Amount IS NOT NULL
UNION ALL
SELECT 'Auxiliary' AS TableName, SUM(Amount) AS Amount
FROM auxiliary
WHERE Category IS NOT NULL AND Amount >0;

SQL Server: Apply different multipliers by date

I have a table that records sales and I want a report on how much tax was paid on each item. The basic rule is all sales before April 1st had a .52% tax, all sales after that date will have a 0.5% tax.
I'm trying to get this using the following query
select ItemCode,
sum(Quantity) QuantitySold,
WhsCode as Store,
case when (docdate < '20170401') then sum(Quantity * .0052) else sum(Quantity * .005) end as Tax
from SalesTable
group by whscode,
itemcode
However I get a
DocDate' is invalid in the select list because it is not contained in
either an aggregate function or the GROUP BY clause.
error if I run it as is. Adding DocDate to the group by clause creates a mess of duplicates (On one example I went from 185 rows to 1508 rows).
Does SQL simply not allow you to use WHEN statements whose conditional is not included in the Group clause or should I be using something else?
Error is because you are using docdate directly without adding it to the group by clause.
I think this is what you want:
select ItemCode,
sum(Quantity) QuantitySold,
WhsCode as Store,
sum(price * case when docdate < '20170401' then 0.0052 else 0.005 end) as Tax
from SalesTable
group by whscode,
itemcode

SQL Query Join plus sum and months sorting

i have a problem using the sum function with the inner join in the below query
SELECT distinct Datename(Month,(date)), year(date), SUM(tblpayment.Amount)
FROM TblSubsc INNER JOIN TBLPayment ON
TblSubsc.[Subsc ID]=TBLPayment.[Subsc ID]
group by year(date),Datename(Month,(date))
it is giving the sum but the months are not sorted so i get
April
August
February
January
March
May
please any help would be appreciated
Try to add the order by clause
order by year(date) asc, month(date) asc
and add
month(date)
to group by too.
EDIT: remove "distinct" as it's not necessary in this case because the data is already grouped by month & date.

How can I optimize a SQL query that performs a count nested inside a group-by clause?

I have a charting application that dynamically generates SQL Server queries to compute values for each series on a given chart. This generally works quite well, but I have run into a particular situation in which the generated query is very slow. The query looks like this:
SELECT
[dateExpr] AS domainValue,
(SELECT COUNT(*) FROM table1 WHERE [dateExpr]=[dateExpr(maintable)] AND column2='A') AS series1
FROM table1 maintable
GROUP BY [dateExpr]
ORDER BY domainValue
I have abbreviated [dateExpr] because it's a combination of CAST and DATEPART functions that convert a datetime field to a string in the form of 'yyyy-MM-dd' so that I can easily group by all values in a calendar day. The query above returns both those yyyy-MM-dd values as labels for the x-axis of the chart and the values from the data series "series1" to display on the chart. The data series is supposed to count the number of records that fall into that calendar day that also contain a certain value in [column2]. The "[dateExpr]=[dateExpr(maintable)]" expression looks like this:
CAST(DATEPART(YEAR,dateCol) AS VARCHAR)+'-'+CAST(DATEPART(MONTH,dateCol) AS VARCHAR) =
CAST(DATEPART(YEAR,maintable.dateCol) AS VARCHAR)+'-'+CAST(DATEPART(MONTH,maintable.dateCol) AS VARCHAR)
with an additional term for the day (ommitted above for the sake of space). That is the source of the slowness of the query, but I don't know how to rewrite the query so that it returns the same result more efficiently. I have complete control over the generation of the query, so if I could find more efficient SQL that returned the same results, I could modify the query generator appropriately. Any pointers would be greatly appreciated.
I havent tested but i think it can be done by:
SELECT
[dateExpr] AS domainValue,
SUM (CASE WHEN column2='A' THEN 1 ELSE 0 END) AS series1
FROM table1 maintable
GROUP BY [dateExpr]
ORDER BY domainValue
The fastest way to do this would be to use calendar tables. Create a sql table with an entry for every month for next who knows how many years. Then select from that calendar table, joining in the entries from table1 that have dates between the start and end date for the month. Then, if your clustered index is on the dateCol in table1, the query will run very quickly.
EDIT: Example Query. This assumes a months table exists with two columns, StartDate and EndDate where EndDate is the midnight on the first day of the next month. The clustered index on the months table should be on StartDate
SELECT
months.StartDate,
COUNT(*) AS [Count]
FROM months
INNER JOIN table1
ON table1.dateCol >= months.StartDate AND table1.dateCol < months.EndDate
GROUP BY months.StartDate;
With Calendar As
(
Select DateAdd(d, DateDiff(d, 0, Min( dateCol ) ), 0) As [date]
From Table1
Union All
Select DateAdd(d, 1, [date])
From Calendar
Where [date] <= (
Select Max( DateAdd(d, DateDiff(d, 0, dateCol) + 1, 0) )
From Table1
)
)
Select C.date, Count(Table1.PK) As Total
From Calendar As C
Left Join Table1
On Table1.dateCol >= C.date
And Table1.dateCol < DateAdd(d, 1, C.date )
And Table1.column2 = 'A'
Group By C.date
Option (Maxrecursion 0);
Rather than try to force the display format in SQL, you should do that in your report or chart generator. However, what you can do in the SQL is to strip the time portion from the datetime values as I've done in my solution.

Resources