I want to get a previous year and month as id from my data but the result is not not correct - ssms

select
(year(dt)*100)+month(dt) as month_id,
(year(dt)*100)+month(dt)-1 as month_id_LM,
Level_6 as Model_Name,
max(Unit_PriceOTR) as OTR_Highest,
min(Unit_PriceOTR) as OTR_Lowest
from
edw.[eview].[TB_R_CARPRICEOTR_APM]
where Level_6 = 'TOYOTA YARIS'
group by
(year(dt)*100)+month(dt),
Level_6
order by month_id
--month_id_LM shows month 0 which does not make sense.

You can group by DATEFROMPARTS which will give you the first day in that month. Then you can just subtract a month:
select
v.month_id,
dateadd(month, -1, v.month_id) as month_id_LM,
Level_6 as Model_Name,
max(Unit_PriceOTR) as OTR_Highest,
min(Unit_PriceOTR) as OTR_Lowest
from
edw.[eview].[TB_R_CARPRICEOTR_APM]
cross apply (values
(datefromparts(year(dt), month(dt), 1))
) v(month_id)
where Level_6 = 'TOYOTA YARIS'
group by
v.month_id,
Level_6
Level_6
order by
month_id;

I am pretty sure there are functions to help you. On a quick search, I could find the DATEADD function.
You can read about it here: https://www.w3schools.com/sql/func_sqlserver_dateadd.asp
One of the examples is this one:
Subtract two months from a date, then return the date:
SELECT DATEADD(month, -2, '2017/08/25') AS DateAdd;

Related

SQL group by fiscal/financial year

Quick question, using the code below I just want to create a field displaying the records fiscal year and then group the results by the year.
The code to retrieve the results works however it does not want to group them by the fiscal year. I just get errors. I have tried multiple combinations using the forums but I can't get it to work. It is doing my head in!
This could be simple to resolve but I can't see it. Could anyone help?
Thanks!
Select m.jobno, m.premid, m.address,m.COMPDATE,
year(dateadd(month, -3, m.COMPDATE)) as FiscalYear
FROM miscvisit m
----- GROUP BY year(dateadd(month, -3, m.COMPDATE))
Try the below query..
SELECT m.jobno
,m.premid
,m.address
,m.COMPDATE
,YEAR(DATEADD(MONTH, - 3, m.COMPDATE)) AS FiscalYear
FROM miscvisit m
GROUP BY m.jobno
,m.premid
,m.address
,m.COMPDATE
,YEAR(DATEADD(MONTH, - 3, m.COMPDATE))
Try this:
Select m.jobno, m.premid, m.address,
year(dateadd(month, -3, m.COMPDATE)) as FiscalYear, sum([SalesField]) as Sales
FROM miscvisit m
GROUP BY
m.jobno, m.premid, m.address,
year(dateadd(month, -3, m.COMPDATE))
Given that you seem to want to return the entire record, perhaps you really want an ORDER BY clause here:
SELECT
jobno,
premid,
address,
COMPDATE,
YEAR(DATEADD(month, -3, COMPDATE)) AS FiscalYear
FROM miscvisit
GROUP BY
YEAR(DATEADD(month, -3, COMPDATE))
ORDER BY
FiscalYear;

SQL How can I get a count of messages going out by month

I have a table that sends out messages, I would like to get a total count of the messages that have been going out month by month over the last year . I am new to SQL so I am having trouble with it . I am using MSSQL 2012 this is my sql
SELECT sentDateTime, MessageID, status AS total, CONVERT(NVARCHAR(10), sentDateTime, 120) AS Month
FROM MessageTable
WHERE CAST(sentDateTime AS DATE) > '2017-04-01'
GROUP BY CONVERT(NVARCHAR(10), sentDateTime, 120), sentDateTime, MessageID, status
ORDER BY Month;
I think the month() and year() functions are more convenient than datepart() for this purpose.
I would go for:
select year(sentDateTime) as yr, month(sentDateTime) as mon, count(*)
from MessageTable
where sentDateTime > '2017-04-01'
group by year(sentDateTime), month(sentDateTime)
order by min(sentDateTime);
Additional notes:
Only include the columns in the select that you care about. This would be the ones that define the month and the count.
Only include the columns in the group by that you care about. Every combination of the expressions in the group by found in the data define a column.
There is no need to convert sentDateTime to a date explicitly for the comparison.
The order by orders the results by time. Using the min() is a nice convenience.
Including the year() makes sure you don't make a mistake -- say by including data from 2018-04 with 2017-04.
-- this selects the part of the date you are looking for, replace this with the date format you are using, this should give you what you are looking for
SELECT DATEPART(mm, GETDATE())
SELECT COUNT(DATEPART(mm, sentDateTime)), MessageID, status
From MessageTable where Cast(sentDateTime as date) > '2017-04-01'
group by DATEPART(mm, sentDateTime), MessageID, status
order by DATEPART(mm, sentDateTime)
You can group by the month number of the sentDateTime with the function DATEPART(MONTH, sentDateTime). The next select will also yield results if no message was sent for a particular month (total = 0).
;WITH PossibleMonths AS
(
SELECT
M.PossibleMonth
FROM
(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) M(PossibleMonth)
),
MonthTotals AS
(
select
COUNT(1) AS Total,
DATEPART(MONTH, sentDateTime) [Month]
From
MessageTable
where
Cast(sentDateTime as date) > '2017-04-01'
group by
DATEPART(MONTH, sentDateTime)
)
SELECT
P.PossibleMonth,
Total = ISNULL(T.Total, 0)
FROM
PossibleMonths AS P
LEFT JOIN MonthTotals AS T ON P.PossibleMonth = T.Month

get last 3 month on year in sql server

I want to get last 3 months name from current month. For example current month is December. So, I want get like this October, November and December.
This is my query:
SELECT CONVERT(CHAR, DATENAME(MONTH, IssueDate)) AS MonthName, ItemId
FROM dbo.Issue AS Issue
GROUP BY CONVERT(CHAR, DATENAME(MONTH, IssueDate)), ItemId
HAVING (ItemId = 427)
This returns:
But, my need is:
N.B. When December month close and January month open then October auto excluded as like (November, December and January)
this link is my Database only 2 table (size-243 KB with Zip) on the google drive https://goo.gl/S4m0R5
Add a date diff in a where clause to filter to the last 3 months, and then order by the month number at the end:
SELECT CONVERT(CHAR, DATENAME(MONTH, [IssueDate])) AS MonthName, ItemId
FROM [dbo].[Issue] AS Issue
WHERE datediff(m, [IssueDate], getdate()) between 0 and 2
GROUP BY CONVERT(CHAR, DATENAME(MONTH, [IssueDate])), ItemId, MONTH(IssueDate)
HAVING (ItemId= 427)
order by MONTH(IssueDate);
You can use DATEADD function:
WHERE IssueDate >= dateadd( month, -2, dateadd( day, -datepart( day, getdate() ) + 1, cast( getdate() as date ) ) )
That will give you IssueDate >= '2015-10-01' given today.
That will also work with index you have on IssueDate, if you start doing something like DATEADD / DATEDIFF etc. on IssueDate then the index can only be scanned end-to-end because it needs to processs all rows in the table so renders the index significantly less effective.
DECLARE #t TABLE
(
IssueDate DATETIME,
ItemId INT
)
INSERT INTO #t (IssueDate, ItemId)
VALUES
('20160105', 427),
('20151212', 427),
('20151213', 427),
('20151110', 427),
('20151001', 427),
('20150905', 427)
SELECT DATENAME(MONTH, dt)
FROM (
SELECT DISTINCT TOP(3) DATEADD(MONTH, DATEDIFF(MONTH, 0, IssueDate), 0) AS dt
FROM #t
WHERE ItemId = 427
ORDER BY dt DESC
) t
results -
------------------------------
January
December
November
You can use a recursive CTE to get month names for the last 12 months and then limit it to the last 3 month names in the second part of the query:
;WITH months(MonthNumber) AS
(
SELECT 0
UNION ALL
SELECT MonthNumber+1
FROM months
WHERE MonthNumber < 12
)
SELECT DATENAME(MONTH,DATEADD(MONTH,-MonthNumber,GETDATE())) AS [month]
FROM dbo.Issue AS Issue
CROSS JOIN months m
WHERE m.MonthNumber <3
GROUP BY DATENAME(MONTH,DATEADD(MONTH,-MonthNumber,GETDATE())) , ItemId
HAVING (ItemId = 427)

How to count number of records per month over a time period

Is there a way to run a query for a specified amount of time, say the last 5 months, and to be able to return how many records were created each month? Here's what my table looks like:
SELECT rID, dateOn FROM claims
SELECT COUNT(rID) AS ClaimsPerMonth,
MONTH(dateOn) AS inMonth,
YEAR(dateOn) AS inYear FROM claims
WHERE dateOn >= DATEADD(month, -5, GETDATE())
GROUP BY MONTH(dateOn), YEAR(dateOn)
ORDER BY inYear, inMonth
In this query the WHERE dateOn >= DATEADD(month, -5, GETDATE()) ensures that it's for the past 5 months, the GROUP BY MONTH(dateOn) then allows it to count per month.
And to appease the community, here is a SQL Fiddle to prove it.
Unlike the other two answers, this will return all 5 months, even when the count is 0. It will also use an index on the onDate column, if a suitable one exists (the other two answers so far are non-sargeable).
DECLARE #nMonths INT = 5;
;WITH m(m) AS
(
SELECT TOP (#nMonths) DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-number, 0)
FROM master.dbo.spt_values WHERE [type] = N'P' ORDER BY number
)
SELECT m.m, num_claims = COUNT(c.rID)
FROM m LEFT OUTER JOIN dbo.claims AS c
ON c.onDate >= m.m AND c.onDate < DATEADD(MONTH, 1, m.m)
GROUP BY m.m
ORDER BY m.m;
You also don't have to use a variable in the TOP clause, but this might make the code more reusable (e.g. you could pass the number of months as a parameter).
SELECT
count(rID) as Cnt,
DatePart(Month, dateOn) as MonthNumber,
Max(DateName(Month, dateOn)) as MonthName
FROM claims
WHERE dateOn >= DateAdd(Month, -5, getdate())
GROUP BY DatePart(Month, dateOn)

Grouping by Week in SQL, but displaying full datetime?

the following statement:
group by datepart(wk, createdon)
Groups the selected rows according to the week in which they fall. My select statement shows the following:
SELECT
datepart(wk, createdon) week,
How do I display the actual datetime of the week("12-10-2012"), instead of the number ("12")?
If I understand you correctly, you're wanting to group by week but also return the full datetime. You must include the selected fields in aggregate columns.
Thusly should work:
SELECT DATEPART(wk, createdon) week, createdon
FROM TableName
GROUP BY DATEPART(wk, createdon), createdon
Works on MSSQL2008R2
Edit:
As the OP seems to want the starting date of the week, SO has the answer.
One option is using a cte with ROW_NUMBER instead:
WITH CTE AS
(
SELECT
RN = ROW_NUMBER() OVER (PARTITION BY datepart(wk, createdon) ORDER BY createdon)
, DATEADD(ww, DATEDIFF(ww,0,createdon), 0) As Week
, *
FROM dbo.Table
)
SELECT * FROM CTE
WHERE RN = 1
You can't group by a week, and then show constituent parts of it, i.e. days. You will need group by the date instead.