Sort by text (nvarchar) - sql

Not sure how to sort with column 'DateText' column like this:
April 2020
March 2001
May 2020
June 2021
December 2021
Expect result
December 2021
June 2021
March 2001
May 2020
April 2020
I tried this but no luck
ORDER BY
CASE WHEN 1 = ISNUMERIC(TextDate)
THEN CAST(TextDate AS INT)
END

Happily, your format can be converted to a date:
order by convert(date, textdate)
You actually want desc for your example.

To build a little on the good answer and advice given here, once the data is in a date datatype there are useful functions you can use to get specific information out of your date, such as the day of the week or the month name and so much more. These can then also be used to order your dates in many different ways should you require it!
Below I have made a little demo of the DATEPART and DATENAME functions, there are far more than this too.
https://www.w3schools.com/sql/func_sqlserver_datename.asp
This was written and tested in T-SQL for MS SQL Server
DECLARE #Dates TABLE(textdate nvarchar(15))
INSERT INTO #Dates
VALUES ('April 2020'),
('March 2001'),
('May 2020'),
('June 2021'),
('December 2021')
SELECT *,
CONVERT(date, textdate) AS datetype
INTO #dates
FROM #Dates
ORDER BY CONVERT(date, textdate) desc
SELECT *,
DATEPART(DD,datetype) AS DayNum,
DATEPART(MM,datetype) AS MonthNum,
DATEPART(YYYY,datetype) AS YearNum,
DATENAME(WEEKDAY, datetype) AS DayName,
DATENAME(MONTH, datetype) AS MonthName
FROM #dates
ORDER BY datetype desc
DROP TABLE #dates

Related

How to get month and year from date in SQL

I need help to get month and year from a date which is in yyyymmdd format.
The dates look like this, '20150102', the output should be Jan 2015.
I want the output as on single value, currently using datepart function Im getting output in 2 different columns for month and year
This may help:
SQL Server:
SELECT FORMAT (GETDATE(), 'MMM yyyy') -- Jul 2019
SELECT FORMAT (GETDATE(), 'MMMM yyyy') -- July 2019
SELECT RIGHT(CONVERT(VARCHAR(11), GETDATE(), 106), 8) -- Jul 2019
For more details: https://www.tutorialgateway.org/sql-date-format/
MySQL:
SELECT DATE_FORMAT("20150102", "%M %Y"); -- January 2015
SELECT DATE_FORMAT("20150102", "%b %Y"); -- Jan 2015
SELECT YEAR(date) AS 'year', MONTH(date) AS 'month'
For more details: http://www.sqlines.com/mysql-to-oracle/date_format
MySQL will recognize the date string as a date, so you can use date_format() to get the format you want:
select date_format('20150102', '%b %Y')
there is a list of all differnet sql date formats sql date formats

Sum of numbers from previous year month until this years month in SQL

Being a beginner, I'm having a hard time coding this particular scenario in SQL Server 2008
As you can see,
The SUM column for July 2017 for example is equal to the following:
August to Dec 2016 + Jan to July 2017 = 4625
Similarly, the SUM column for August 2017 is equal to the following:
Sep to Dec 2016 + Jan to August 2017 = 4625
How can I automate this from month to month?
I appreciate any help I can get. Trying to code this in SQL Server 2008
Using this methodology to find the first day of the current month:
select dateadd(month, datediff(month, 0, getdate()), 0)
We can expan on it to get the first day, of the next month, a year ago... i.e. 11 months ago.
select dateadd(month, datediff(month, 0, dateadd(month,-11,getdate())), 0)
Then, we just need to use it in a where clause to limit your data...
declare #startDate = (select dateadd(month, datediff(month, 0, dateadd(month,-11,getdate())), 0))
declare #endDate = getdate()
select sum(someColumn)
from someTable
where dateColumn between #startDate and #endDate
Since you didn't provide your actual data set, just some pivoted data, I'm not sure of your column and table names
This sounds like you want window functions. Assuming your data is already summarized by month:
select t.*,
sum(numbers) over (order by yyyymm rows between 11 preceding and current row) as prev_12_sum
from t;
If the data is not already summarized, you can put this in a group by as well:
select year(date), month(date),
sum(sum(numbers)) over (order by year(date), month(date) rows between 11 preceding and current row) as prev_12_sum
from t
group by year(date), month(date)
order by min(date);

last date of Financial year (I.e 2017-03-31)

Hi please let me know how to extract the last day of Financial year in sql server.my financial year start from 2016-04-01 to 2017-03-31
Closest you can use is End Of Month for that you need to provide one date to that month as below:
select eomonth('2017-03-01')
To get the last day of the financial year for any date, you need to find the last of march if before march, or the last of march next year if after march:
declare #yourdate datetime = getdate();
select case when month(#yourdate) < 4 then CONVERT(datetime,cast(YEAR(#yourdate) as char(4)) + '-03-31' ,120)
else CONVERT(datetime,cast(YEAR(#yourdate) + 1 as char(4)) + '-03-31' ,120)
end as financial_year_end
Edit:
If you want last date derived based on from_date, then use something like this
Rextester Demo
select
case when datepart(mm,from_date) <=3 then
cast(concat(year(from_date),'-03-31') as datetime)
else
dateadd(year,1,cast(concat(year(from_date),'-03-31') as datetime))
end as last_date_fin
from
(select '2017-04-30' as from_date union all
select '2017-01-13') t;
This way from_date between Jan - Mar will give same year's 31st march. Else it will give next year's 31st March.
Previous answer:
http://rextester.com/AXVM26769
If you want to get last day of march for same year as passed, then use
select cast(concat(given_year,'-03-31') as datetime)
from
(select '2017' as given_year) t
If you want to pass 2016 and then get 2017-03-31 then use. You can change the year in derived table and change the output based on that.
select dateadd(year,1,cast(concat(given_year,'-03-31') as datetime))
from
(select '2016' as given_year) t;
This Code will work to find the last date of Financial Year.
For Previous Year case matches and 'THEN' part will Execute and for current year 'ELSE'
part will execute.
select CASE WHEN (MONTH(GETDATE())) <= 3
THEN convert(varchar(4), YEAR(GETDATE())-1) + '-' + '03-31'
ELSE convert(varchar(4),YEAR(GETDATE()))+ '-' + '03-31'
end
> LastDayOfYearFY] =
> eomonth( dateadd(month, 5,
> dateadd(year, datepart(year, (dateadd(month, 6, [date])) ) -1900, 0)))
Idea extension taken from return-first-day-of-financial-year
You can select all the dates order them descendant and take the first one.
SELECT date
FROM table
ORDER BY date desc
LIMIT 1;

How to group daily data on weekly basis using sql

I am trying to group the number of hours that employees worked for the last 4 weeks but I want to group them on a weekly basis. For example:
WEEK HOURS
Feb 24 to March 2 55
March 3 to March 9 40
March 10 to March 16 48
March 17 to March 23 37
This is what I have so far, please help. thanks
SET DATEFIRST 1
SELECT CAST(MIN( [DT]) AS VARCHAR(20))+' TO '+CAST (MAX([DT]) AS VARCHAR(20)) AS DATE,
SUM(HOURS) AS NUM_HRS
FROM MyTable
GROUP BY DATEPART(WEEK,[DT])
HAVING COUNT(DISTINCT[DT])=7
Create a Calendar auxilliary table, with Year, Month, Week, Date columns (you can also add holidays and other interesting stuff to it, it has many potential uses) and populate it for the period of interest.
After that, it's as easy as this:
SELECT sum(hours), cast(min(date) as varchar), cast(max(date) as varchar)
FROM Calendar c
LEFT OUTER JOIN MyTable h on h.Date = c.date
GROUP BY year, week
ORDER BY year, week
SET DATEFIRST 1
SELECT DATEPART(WEEK,DT) AS WEEK,
SUM(HOURS) AS NUM_HRS
FROM MyTable
WHERE DT >= DATEADD(WEEK, -4, GetDate()),
GROUP BY DATEPART(WEEK,[DT])
Try something like
SELECT
DATEADD(DD,
CONVERT(INT, (DATEDIFF(DD, '1/1/1900', t.DT)/7)) * 7,
'1/1/1900') [WeekBeginDate],
DATEADD(DD,
(CONVERT(INT, (DATEDIFF(DD, '1/1/1900', t.DT)/7)) * 7) + 6,
'1/1/1900') [WeekEndDate],
SUM(HOURS) AS NUM_HRS
FROM MyTable t
GROUP BY CONVERT(INT, DATEDIFF(DD, '1/1/1900', t.DT)/7)
Though this is the brute force trick, I think in your case it will work.
EDIT : Modified the query a little bit, the error was caused because of the order in which DATEDIFF calculates the difference.
Also here is a SQL FIDDLE with a working example.
EDIT 2 : Updated the Fiddle with the Date Format. To customize the date format, this article would help.

Calculate date based on pattern from anchor date

I have a rolling 4 week (28 day) date pattern starting from an anchor date in the past. I need to know what the nearest previous pattern start date is relative to the current date.
For example:
Anchor date = Monday June 30 2013. If today's date is August 7 2013 then the date I would like returned is July 29 2013. Previous pattern start dates were June 30, July 29. The next pattern start date is August 26 but that is after today's date of August 7 2013.
Hope that makes sense and thanks
While I'm not 100% sure I understand where July 29th comes from, if you want to retrieve the closest date 28 days from an anchor date, one way would be to use a recursive CTE (although it could have a performance implication).
declare #anchor datetime
set #anchor = '6/30/2013'
;with cte as (
select #anchor dt
union all
select dateadd(day, 28, dt) dt
from cte
where dt <= dateadd(day, -28, '8/7/2013')
)
select max(dt) from cte
SQL Fiddle Demo
Perhaps an even simpler solution would be to use datediff as well:
declare #anchor datetime
set #anchor = '6/30/2013'
select dateadd(day, 28 * (datediff(day, #anchor, getDate())/28), #anchor)
More Fiddle
I think your calculation is a little off. 28 days after 30/Jun in 28/Jul then 25/Aug.
Anyways, here is my query which will return 28/Jul, which I believe to be the correct answer.
WITH my_date AS
(SELECT CAST('30/Jun/2013' AS DATETIME)AS the_date
UNION ALL
SELECT dateadd(day,28,the_date)AS the_date
FROM my_date
WHERE my_date.the_date <= dateadd(day,-28,getdate())
)
SELECT max(the_date)
FROM my_date
http://sqlfiddle.com/#!6/d41d8/6267