SQL Query Select help, monthly report - sql

I am new to SQL and I need help to make a view from a table in my SQL Server. I have a sales table and need to have a monthly sales report with distinct clientid.
This is what my sales table looks like:
ID Name Amount Date
1 James 300.00 29-09-2015
1 James 250.00 30-09-2015
4 Carl 100.00 30-09-2015
5 Peter 500.50 01-10-2015
5 Peter 300.00 25-10-2015
Desired output:
ID Name Total Month/Year
1 James 550.00 September 2015
4 Carl 100.00 September 2015
5 Peter 800.50 October 2015

You could do something like this:
SELECT
ID,
Name,
SUM(Amount) AS Total,
DATENAME(mm, [Date]) + ' ' + DATENAME(yy, [Date]) AS Month_Year
FROM
<sales table>
GROUP BY
ID,
Name,
DATENAME(mm, [Date]) + ' ' + DATENAME(yy, [Date])
ORDER BY
ID,
Name,
DATENAME(mm, [Date]) + ' ' + DATENAME(yy, [Date])
Aggregating data to produce totals is a very common scenario in SQL, but you should probably start off learning the basics. There are plenty of online resources for this e.g. http://www.w3schools.com/sql/sql_groupby.asp

SELECT
ID,
Name,
SUM(Amount) AS Total,
DATENAME( MONTH , DATEADD( MONTH , DATEPART(MONTH, Date) , -1 )) + ' ' + CAST(DATEPART(YEAR, Date) AS VARCHAR(4)) AS "Month/Year"
FROM SALES_TABLE
GROUP BY
ID, Name, DATEPART(YEAR, Date), DATEPART(MONTH, Date)

Related

Grouping several years' data by week

I am using Covid world data, which tracks number of new_cases every day. I have data from 2020-01-01 to present day. This is my current query:
SELECT MIN(date) as week, datepart(iso_week, date) week_num, sum(new_cases) as [Total Cases]
FROM covid_data_cleaned
GROUP BY DATEPART(iso_week, date), DATEPART(year, date)
ORDER BY MIN(date) DESC
Which gives me pretty much what I want except for when the year changes:
week week_num Total Cases
2022-01-10 2 20803473
2022-01-03 1 17217248
**2022-01-01 52 2115780**
**2021-12-27 52 7971560**
2021-12-20 51 5561762
I want to figure out the workaround to combining the '52' values together. Alternatively, my dataset has 112 weeks; can I assign the values 1-112 to the whole dataset rather than 1-52 for each year?
You could aggregate on a correction via a CASE WHEN for the iso year.
SELECT
min(weekstart) as [week]
, [iso_week] as weeknum
, sum(new_cases) as [Total Cases]
FROM
(
SELECT
min([date]) as weekstart
, datepart(iso_week, [date]) as [iso_week]
, case
when month(min([date])) = 1
and datepart(iso_week, [date]) >= 52
then year([date]) - 1
when month(min([date])) = 12
and datepart(iso_week, [date]) = 1
then year([date]) + 1
else year([date])
end as iso_year
, sum(new_cases) as new_cases
FROM covid_data_cleaned
GROUP BY year([date]), datepart(iso_week, [date])
) q
GROUP BY iso_year, [iso_week]
ORDER BY [week] DESC;
Instead of iso week, you can use week.
DECLARE #table table(datev date, new_Cases int)
INSERT INTO #table values
('2022-01-01',123),('2022-01-09',432),('2022-01-03',123),('2021-12-27',234);
SELECT MIN(datev) as week, datepart(week, datev) week_num, sum(new_cases) as [Total Cases]
FROM #table
GROUP BY DATEPART(week, datev), DATEPART(year, datev)
ORDER BY MIN(datev) DESC
week
week_num
Total Cases
2022-01-09
3
432
2022-01-03
2
123
2022-01-01
1
123
2021-12-27
53
234

How to get sum by MonthYear in sql?

I have a table like this
id Date Amount
1 2016-09-29 09:25:37.000 25.13
2 2016-08-01 17:20:39.000 598.00
3 2016-09-29 09:24:47.000 15.60
4 2016-07-28 17:50:11.000 61.80
5 2016-07-28 17:53:56.000 31.40
6 2016-07-22 10:40:27.000 74.16
I'm trying to get two columns like this,
MonthYear Total
Sep 2016 40.73
Aug 2016 598.00
Jul 2016 167.36
But, I want to get most recent year and month to top.
Try this sql,
SELECT CONVERT(CHAR(4), Date, 100) + CONVERT(CHAR(4), Date, 120)
AS MonthYear, SUM(Amount)
AS Total,
CAST(CONVERT(varchar(4), Date, 120) AS int)
AS Year, DATEPART(m, Date) As Month
FROM your_table
GROUP BY CONVERT(CHAR(4), Date, 100) + CONVERT(CHAR(4), Date,120),CAST(CONVERT(varchar(4), Date, 120) AS int), DATEPART(m, Date)
ORDER BY Year DESC, Month DESC
Just an other perspective.
Query
SELECT t.[MonthYear], SUM(t.[Amount]) AS [Total] FROM(
SELECT RIGHT((CONVERT(VARCHAR(11), [Date], 106)), 8) as [MonthYear], [Amount]
FROM [your_table_name]
)t
GROUP BY t.[MonthYear];
Try below
SELECT Datename(MONTH, [Date]) month_name,
Year([Date]) year,
Sum([Amount]),
Month([date]) month_no
FROM #Table1
GROUP BY Datename(MONTH, [Date]),
Year([Date]),
Month([date])
ORDER BY Month([date]) DESC,
Year([Date]),
Datename(MONTH, [Date])

Sum of sales by Quarter

How can i use SQL and SUM monthly data (quarter view)? I will not use Stored Procedures etc.
Current data:
ID | Sales
201601 | 5
201602 | 15
201603 | 5
201604 | 20
201605 | 8
201606 | 2
...
My ID column is like yyyymm
What I want is:
Quarter | Sales
Q1 | 25
Q2 | 30
....
You can try a query like below
SELECT
LEFT(ID,4) Year,
'Q'+ CAST((CAST(RIGHT(ID,2) AS INT)-1 )/3 +1 AS varchar) Quarter,
SUM(Sales) Sales
FROM
Yourtable
GROUP BY
LEFT(ID,4),
'Q'+ CAST((CAST(RIGHT(ID,2) AS INT) -1 )/3 +1 AS varchar)
order by year
SQL demo link
You can use DATEPART and QUARTER to get the quarter of a DATETIME. You just need to build the DATETIME using DATEFROMPARTS and parsing your ID column.
The CONCAT just adds 'Q' to the period number.
SELECT LEFT(id,4) [Year],
CONCAT('Q',DATEPART(QUARTER, DATEFROMPARTS(LEFT(id,4), RIGHT(id, 2), 1))) [Quarter],
SUM(Sales) [Sales]
FROM yourtable
GROUP BY LEFT(id,4), DATEPART(q, DATEFROMPARTS(LEFT(id,4), RIGHT(id, 2), 1))
ORDER BY [Year], [Quarter]

sql server calculate cumulative number per month for different year

I have a table with "date" column. Each row represents a survey.
date
11/19/2013 5:51:41 PM
11/22/2013 1:30:38 PM
11/23/2013 3:09:17 PM
12/2/2014 5:24:17 PM
12/25/2014 11:42:56 AM
1/6/2014 2:24:49 PM
I want to count the number of survey per month cumulatively. As you see from the above table, there are 3 surveys for Nov 2013, 2 surveys for Dec 2013, 1 survey for Jan 2014. The cumulative number of survey per month would be:
month | year | number_of_survey
11 | 2013 | 3
12 | 2013 | 5
1 | 2014 | 6
I have this query which shows correct number of surveys for 2013, and number of survey for 2014 is not cumulative.
with SurveyPerMonth as -- no of Survey per month
(
select datepart(month, s.date) as month,
datepart(year, s.date) as year,
count(*) as no_of_surveys
from myTable s
group by datepart(year, s.date), datepart(month, s.date)
)
select p1.month, p1.year, sum(p2.no_of_surveys) as surveys -- cumulatively
from SurveyPerMonth p1
inner join SurveyPerMonth p2 on p1.month >= p2.month and p1.year>=p2.year **-- the problem is probably comes from this line of code**
group by p1.month, p1.year
order by p1.year, p1.month;
This query returns:
month | year | surveys
11 | 2013 | 3
12 | 2013 | 5
1 | 2014 | 1 // 2014 is not cumulative
How can I calculate cumulative number of surveys per month for 2014 as well?
Something like this ?
SELECT date = create_date INTO #myTable FROM master.sys.objects
;WITH perMonth ( [year], [month], [no_of_surveys])
AS (SELECT DatePart(year, s.date) ,
DatePart(month, s.date),
COUNT(*)
FROM #myTable s
GROUP BY datepart(year, s.date),
datepart(month, s.date))
SELECT [year],
[month],
[no_of_surveys] = ( SELECT SUM([no_of_surveys])
FROM perMonth agg
WHERE (agg.[year] < pm.[year])
OR (agg.[year] = pm.[year] AND agg.[month] <= pm.[month]))
FROM perMonth pm
ORDER BY [year], [month]
Edit: seems I missed the ball with < and >, fixed it and added small example
'--This should work.I have added a new column 'monthyear'
with surveypermonth as -- no of survey per month
(
select datepart(month, s.date) as month,
datepart(year, s.date) as year,
datepart(year, s.date) *100 + datepart(month, s.date) as monthyear,
count(*) as no_of_surveys
from test s
group by datepart(year, s.date), datepart(month, s.date),datepart(year, s.date)*100 + datepart(month, s.date)
)
select a.month,substring(cast(monthyear as varchar(6)),1,4) as year,surveys from
(
select p1.month, p1.monthyear as monthyear, sum(p2.no_of_surveys) as surveys
from surveypermonth p1
inner join surveypermonth p2 on p1.monthyear>=p2.monthyear
group by p1.month, p1.monthyear
--order by p1.monthyear, p1.month
)a

Select sum of items based on their monthly entry date

I am trying to select sum of items based on their monthly entry date:
The Inventory table is as below:
EntryDate Items
1/1/2013 2
1/20/2013 5
1/23/2013 3
1/30/2013 2
2/4/2013 4
2/17/2013 34
The desired output with Total row added:
EntryDate Items
1/1/2013 2
1/20/2013 5
1/23/2013 3
1/30/2013 2
**Total 12**
2/4/2013 4
2/17/2013 34
**Total 38**
Below is my attempt. I am trying to do this using rollup but its counting all items at once and not by monthly basis, how to achieve this:
Select Convert(date, EntryDate) AS [DATE],SUM(Items) AS Total,
Case WHEN GROUPING(Items) = 1 THEN 'Rollup'
Else Status end AS Total From [Inventory] Group by Convert(date, EntryDate) WITH
Rollup
If you actually want results like your example, you can use the following:
SELECT EntryDate, Items
FROM (SELECT YEAR(EntryDate)'Year_',MONTH(EntryDate)'Month_',CAST(EntryDate AS VARCHAR(12))'EntryDate',Items,1 'sort'
FROM Inventory
UNION ALL
SELECT YEAR(EntryDate)'Year_',MONTH(EntryDate)'Month_','Total',SUM(Items)'Items',2 'sort'
FROM Inventory
GROUP BY YEAR(EntryDate),MONTH(EntryDate)
)sub
ORDER BY Year_,Month_,sort
Demo: SQL Fiddle
Try this, it will give you the month total in a new column, it will also work when your dates stretch over more than 1 year
SELECT EntryDate, Items,
SUM(Items) OVER (partition by dateadd(month, datediff(month, 0, entrydate), 0)) Total
FROM [Inventory]
Result:
EntryDate Items Total
2013-01-01 2 12
2013-01-20 5 12
2013-01-23 3 12
2013-01-30 2 12
2013-02-04 4 38
2013-02-17 34 38
DATEPART will do try this,
SELECT DATEPART(month, EntryDate) AS 'Month Number',sum(items1) FROM ITEMS
GROUP BY DATEPART(month, EntryDate)
# sqlfiddle
Try:
select entryDate, Items, sum(Items)
from (select entryDate,Items, to_date(entry_date, 'mm/yyyy') month_date from Inventory)
group by month_date
Here's a perfect solution for you
select isnull(cast(DATEFROMPARTS(year,month,day) as varchar),'Total'),
items
from ( SELECT datepart(yyyy,EntryDate) year,
DATEPART(mm, EntryDate) month,
DATEPART(dd, EntryDate) day,
sum(items) items
From Inventory
GROUP BY
ROLLUP (datepart(yyyy,EntryDate),
DATEPART(mm, EntryDate),
DATEPART(dd, EntryDate)
)
) a
where a.year is not null
and a.month is not null;
Demo HERE