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
Related
I'm trying to list the total number of orders for the last 12 rolling months (not including the current month).
This is my query:
Select
Year(CreatedOn)*100+Month(CreatedOn) YearMonth,
Count(*) OrderCount
From Orders
Where DateDiff(MM,CreatedOn,GetUTCDate()) Between 1 And 12
Group By Year(CreatedOn), Month(CreatedOn)
Order By YearMonth
As expected, I am getting the results correctly. However, when there are no orders in a specific month, the month is excluded from the result completely. I would like to show that month with 0. See sample result:
201809 70
201810 8
201811 53
201812 67
201901 15
201902 13
201903 10
201905 12
201908 9
See the missing months 201904, 201906 and 201907. There should be a total of 12 rows.
The query should be executable within a sub-query using For XML Path so that I can get a comma separated list of orders in the last 12 months.
How can I accomplish this?
You need to generate the rows that you want somehow. One method uses a recursive CTE:
with dates as (
select Year(getdate())*100+Month(getdate()) as yearmonth,
1 as n, datefromparts(year(getdate()), month(getdate()), 1) as yyyymm
union all
select year(dateadd(month, -1, yyyymm)) * 100 + month(dateadd(month, -1, yyyymm),
n + 1,
dateadd(month, -1, yyyymm)
from cte
where n < 12
),
q as (
<your query here>
)
select d.yearmonth, coalesce(q.orders, 0) as orders
from dates d left join
q
on d.yearmonth = q.yearmonth;
Check this-
WITH R(N) AS
(
SELECT 1
UNION ALL
SELECT N+1
FROM R
WHERE N < 12
)
SELECT REPLACE(LEFT(CAST (DATEADD(MONTH,DATEDIFF(MONTH,0,(DATEADD(MONTH,-N,GetUTCDate()))),0) AS DATE),7),'-','') AS [YearMonth],ISNULL(o.OrderCount,0) as OrderCount
FROM R A
LEFT JOIN
(
Select
Year(CreatedOn)*100+Month(CreatedOn) YearMonth,
Count(*) OrderCount
From Orders
Where DateDiff(MM,CreatedOn,GetUTCDate()) Between 1 And 12
Group By Year(CreatedOn), Month(CreatedOn)
) O ON O.YearMonth=REPLACE(LEFT(CAST (DATEADD(MONTH,DATEDIFF(MONTH,0,(DATEADD(MONTH,-N,GetUTCDate()))),0) AS DATE),7),'-','')
Order By REPLACE(LEFT(CAST (DATEADD(MONTH,DATEDIFF(MONTH,0,(DATEADD(MONTH,-N,GetUTCDate()))),0) AS DATE),7),'-','');
I got a problem while trying to count the entries that were created in a month for the last 6 months.
The table looks like this:
A B C D
Year Month Startingdate Identifier
-----------------------------------------
2019 3 2019-03-12 OAM_1903121
2019 2 2019-03-21 OAM_1902211
And the result should look like:
A B C
Year Month Amount of orders
---------------------------------
2019 3 26
2019 2 34
This is what I have so far, but it doesn't get me the proper results:
SELECT year, month, COUNT(Startingdate) as Amount
FROM table
WHERE Startingdate > ((TRUNC(add_months(sysdate,-3) , 'MM'))-1)
GROUP BY year, month
I have not tested it, but it should work:
select year, month, count(Stringdate) as Amount_of_order
from table
where Stringdate between add_months(sysdate, -6) and sysdate
group by year, month;
Let me know.
Try that :
SELECT YEAR(Startingdate) AS [Year], MONTH(Startingdate) AS [Month], COUNT(*) AS Amount
FROM table
WHERE Startingdate > DATEADD(MONTH, -6, GETDATE())
GROUP BY YEAR(Startingdate), MONTH(Startingdate)
ORDER BY YEAR(Startingdate), MONTH(Startingdate) DESC
I think your issue is the filtering. If so, this should handle the most recent six full months:
SELECT year, month, COUNT(*) as num_orders
FROM table
WHERE Startingdate >= TRUNC(add_months(sysdate, -6) , 'MM')
GROUP BY year, month;
I am trying to figure out how can I get following result by query but unable to do the same.
Table Name: ProductMaster
ProductCode Quantity EntryDate
A1 10 10/03/2015
A1 10 15/03/2015
A2 10 18/03/2015
A2 10 25/03/2015
A1 10 10/04/2015
A2 10 15/04/2015
I want to get result as
If I select March month, result should be as:
ProductCode MonthCount TotalCount
A1 20 30
A2 20 30
If I select April month, result should be as:
ProductCode MonthCount TotalCount
A1 10 30
A2 10 30
My Query:
SELECT ProductCode, SUM(Quantity)
FROM ProductMaster
WHERE DATEPART(MONTH, EntryDate) = #Month
GROUP BY ProductCode
Where #month = 3 or 4, based on input.
Additionally, How can i get the count of productcode.
For Month = 3
ProductCode MonthCount TotalCount
A1 2 3
A2 2 3
You could use a case expression based on #Month:
SELECT ProductCode,
SUM (CASE WHEN MONTH(EntryDate) = #Month THEN Quantity ELSE 0 END)
AS MonthCount,
SUM (Quantity) AS TotalConount
FROM ProductMaster
GROUP BY ProductCode
EDIT:
To answer the edited question, you can use the same technique with count instead of sum:
SELECT ProductCode,
COUNT (CASE WHEN MONTH(EntryDate) = #Month THEN Quantity ELSE NULL END)
AS MonthCount,
COUNT (*) AS TotalConount
FROM ProductMaster
GROUP BY ProductCode
Here is a solution using a Common Table Expression (CTE). This query will get the results for all months in the same resultset. If you only need one month you can add a WHERE clause and filter on MonthNumber for just the month you desire.
;WITH cteProductMasterByMonth AS
(
SELECT ProductCode, DATEPART(MONTH, EntryDate) as MonthNumber, SUM(Quantity) as MonthCount
FROM #ProductMaster
GROUP BY ProductCode, DATEPART(MONTH, EntryDate)
)
SELECT ProductCode, MonthCount, SUM(MonthCount) OVER(PARTITION BY ProductCode) AS TotalCount
FROM cteProductMasterByMonth
ORDER BY MonthNumber, ProductCode
I tested this on SqlFiddle
Note: If the EntryDate values spans multiple years and you want to the results for each month-year pair, then you will need to add an additional condition to in the CTE query to group by DATEPART(YEAR, EntryDate) as well and maybe a YearNumber field similar to the MonthNumber field in the select clause.
I have the following table:
ID GROUPID oDate oValue
1 A 2014-06-01 100
2 A 2014-06-02 200
3 A 2014-06-03 300
4 A 2014-06-04 400
5 A 2014-06-05 500
FF. until the end of the month
30 A 2014-06-30 600
I have 3 kinds of GROUPID, and each group will create one record per day.
I want to calculate the total of oValue from the 2nd day of each month until the end of the month. So the total of June would be from 2/Jun/2014 until 30/Jun/2014. If July, then the total would be from 2/Jul/2014 until 31/Jul/2014.
The output will be like this (sample):
GROUPID MONTH YEAR tot_oValue
A 6 2014 2000
A 7 2014 3000
B 6 2014 1500
B 7 2014 5000
Does anyone know how to solve this with sql syntax?
Thank you.
You can use a correlated subquery to get this:
SELECT T.ID,
T.GroupID,
t.oDate,
T.oValue,
ct.TotalToEndOfMonth
FROM T
OUTER APPLY
( SELECT TotalToEndOfMonth = SUM(oValue)
FROM T AS T2
WHERE T2.GroupID = T.GroupID
AND T2.oDate >= T.oDate
AND T2.oDate < DATEADD(MONTH, DATEDIFF(MONTH, 0, T.oDate) + 1, 0)
) AS ct;
For your example data this gives:
ID GROUPID ODATE OVALUE TOTALTOENDOFMONTH
1 A 2014-06-01 100 2100
2 A 2014-06-02 200 2000
3 A 2014-06-03 300 1800
4 A 2014-06-04 400 1500
5 A 2014-06-05 500 1100
30 A 2014-06-30 600 600
Example on SQL Fiddle
For future reference if you ever upgrade, in SQL Server 2012 (and later) this becomes even easier with windowed aggregate functions that allow ordering:
SELECT T.*,
TotalToEndOfMonth = SUM(oValue)
OVER (PARTITION BY GroupID,
DATEPART(YEAR, oDate),
DATEPART(MONTH, oDate)
ORDER BY oDate DESC)
FROM T
ORDER BY oDate;
Example on SQL Fiddle
EDIT
If you only want this for the 2nd of each month, but still need all the fields then you can just filter the results of the first query I posted:
SELECT T.ID,
T.GroupID,
t.oDate,
T.oValue,
ct.TotalToEndOfMonth
FROM T
OUTER APPLY
( SELECT TotalToEndOfMonth = SUM(oValue)
FROM T AS T2
WHERE T2.GroupID = T.GroupID
AND T2.oDate >= T.oDate
AND T2.oDate < DATEADD(MONTH, DATEDIFF(MONTH, 0, T.oDate) + 1, 0)
) AS ct
WHERE DATEPART(DAY, T.oDate) = 2;
Example on SQL Fiddle
If you are only concerned with the total then you can use:
SELECT T.GroupID,
[Month] = DATEPART(MONTH, oDate),
[Year] = DATEPART(YEAR, oDate),
tot_oValue = SUM(T.oValue)
FROM T
WHERE DATEPART(DAY, T.oDate) >= 2
GROUP BY T.GroupID, DATEPART(MONTH, oDate), DATEPART(YEAR, oDate);
Example on SQL Fiddle
Not sure whether you have data for different years
Select YEAR(oDate),MONTH(oDate),SUM(Value)
From #Temp
Where DAY(oDate)>1
Group By YEAR(oDate),MONTH(oDate)
If you want grouped per GROUPID, year and month this should do it:
SELECT
GROUPID,
[MONTH] = MONTH(oDate),
[YEAR] = YEAR(oDate),
tot_oValue = SUM(ovalue)
FROM your_table
WHERE DAY(odate) > 1
GROUP BY GROUPID, YEAR(oDate), MONTH(oDate)
ORDER BY GROUPID, YEAR(oDate), MONTH(oDate)
This query produces required output:
SELECT GROUPID, MONTH(oDate) AS "Month", YEAR(oDate) AS "Year", SUM(oValue) AS tot_oValue
FROM table_name
WHERE DAY(oDate) > 1
GROUP BY GROUPID, YEAR(oDate), MONTH(oDate)
ORDER BY GROUPID, YEAR(oDate), MONTH(oDate)
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