Sort by Date in SQL - sql

I have a resources table, one of the fields is a date field with the Data Type of date. I want to have to following output:
Current month records (say May - year is not important)
Then the following (again, assuming May is the current month)
June Records
July Records
August Records
September Records
October Records
November Records
December Records
January Records
February Records
March Records
April Records
Come June, June is the current month and then the order would be:
July Records
August Records
...
Here is my SQL...I don't know how to ORDER the output to achieve the desired order (5,6,7,8,9,10,11,12,1,2,3,4):
SELECT
resource_id,
resource_title,
resource_summary,
resource_category,
resource_status,
resource_date,
DATEPART(month, resource_date) AS resource_month,
DATEPART(day, resource_date) AS resource_day
FROM dbo.resources
WHERE (resource_category = N'Quotes')
AND (resource_status <> N'Draft')
I found this possible solution for MySQL:
I need unusual ordering mysql results
but I'm missing something on my end.

ORDER BY
(MONTH(resource_date) - MONTH(GETDATE()) + 12) % 12,
DATEADD(year, YEAR(GETDATE()) - YEAR(resource_date), resource_date),
YEAR(resource_date)
The first term sets the primary order by the month of resource_date (the current month will be first, the previous one, last). The second term orders the timestamps within a month regardless of the year of the date. If your dates do not contain time parts or if the time parts are absolutely irrelevant, you could replace it with DAY(resource_date). Finally, the last term takes the year into account for otherwise identical dates (could also be simply resource_date).

Will it work for you?
ORDER BY
CASE DATEPART(month, resource_date)
WHEN 5 THEN 0
WHEN 6 THEN 1
... etc
END

I think something like this might be what you're looking for:
SELECT
resource_id,
resource_title,
resource_summary,
resource_category,
resource_status,
resource_date
FROM
dbo.resources
WHERE
resource_date >= DATE_FORMAT(NOW() ,'%Y-%m-01') AND
resource_date < DATE_FORMAT(DATE_ADD(NOW(), INTERVAL 1 YEAR) ,'%Y-%m-01')
ORDER BY
resource_date;

How 'bout ORDER BY (DATEPART(month,resource_date) - (DATEPART(month,getdate() -1)) % 12)
So in May (month 5), you order by the month in the row -6 (mod 12). So, June (month 6) would be 0, July (7) would be 1.
In June, July would be 0, etc.

You should be able to adapt the MySQL solution by using DATEPART in place of DATE_FORMAT:
SELECT resource_id, resource_title, resource_summary, resource_category, resource_status, resource_date, DATEPART(month, resource_date) AS resource_month, DATEPART(day, resource_date) AS resource_day
FROM dbo.resources
WHERE (resource_category = N'Quotes') AND (resource_status <> N'Draft')
ORDER BY DATEPART(month, resource_date) < DATEPART(month, GETDATE()),
DATEPART(month, resource_date)
I don't have SQL Server handy so I'm not sure if it will be happy with a boolean in the ORDER BY clause though. If it doesn't like the boolean ORDER BY, then a CASE should do the trick:
ORDER BY
CASE WHEN DATEPART(month, resource_date) < DATEPART(month, GETDATE())
THEN 0
ELSE 1
END,
DATEPART(month, resource_date)

I assume that there is a year within "resource_date" - isn't it?
In this case you can simply filter and order by
WHERE resource_date >= getdate()
AND resource_date < DATEADD(year,1,getdate())
ORDER BY resource_date;
If there is no year (or more exactly: different unknown years) you can do this:
ORDER BY
CASE
WHEN DATEADD(year,-year(resource_date),resource_date) <
DATEADD(year,-year(getdate()),getdate())
THEN 1
ELSE 0
END ASC,
DATEADD(year,-year(resource_date),resource_date);
Hope it helped ...

Related

Trying to display last month data from SQL database - where clause

I am using a where clause to run a query in a system.
The below where clause works when I want to look at data changed in the last 7 days. But I now need to find data changed last month. I do not want last 30 days as I need to have this run each month.
changedate >= dateadd(day,-7,getdate())
Please help? By "Last Month" I mean the previous months data. For example if the report is run on the 5th of July, the data displays results from 1st June - 30th June.
Presumably, you want:
changedate >= dateadd(month, -1, getdate())
EDIT:
If you want the previous complete month:
changedate < datefromparts(year(getdate()), month(getdate()), 1) and
changedate >= dateadd(month, -1, datefromparts(year(getdate()), month(getdate()), 1))
Or, if you don't care about optimizing the query (because this prevents the use of partitions):
datediff(month, changedate, getdate()) = 1
maybe
changedate between DATEADD(DAY,1,EOMONTH(GETDATE(),-2)) and EOMONTH(GETDATE(),-1)
or
month(changedate) = month(getdate()) -1
and year(changedate) = year(getdate())

What is -1 and 0 doing in date add function?

dateadd(mm, DATEPART(MONTH, DATE) - 1, 0) + DATEPART(DAY, DATE) - 1
OUTPUT date is in the year for example 1990-12-02 00:00:00:000
Full query is below:
SELECT dateadd(yy, (
DATEPART(YEAR, GETDATE()) + (
CASE
WHEN DATEPART(MONTH, GP_DATE) > 10
THEN 0
ELSE 1
END
) - 1900
), 0) + dateadd(mm, DATEPART(MONTH, GP_DATE) - 1, 0) + DATEPART(DAY, GP_DATE) - 1 GP_DATE
from table
I am trying to convert this query into snowflake syntax and snowflake syntax dateadd function does not allow 1, 0.
In SQL Server, there are some rather ugly implicit conversions available between datetimes and integers.
0, when converted to a date, becomes 1900-01-01.
You're also allowed to do maths on dates. Adding or subtracting 1 adds or subtracts 1 day from the date. Putting these facts together, we have:
dateadd(yy, (
DATEPART(YEAR, GETDATE()) + (
CASE
WHEN DATEPART(MONTH, GP_DATE) > 10
THEN 0
ELSE 1
END
) - 1900
), 0)
Which is taking the current year, and subtracting 1900 from it (or 1899 if the month is less than 11, for whatever reason). We then take that number and add it back to the date 0 (which as stated above is 1900-01-01). The result is that we get the first of January of next year or this year, depending on the month of GP_DATE. Call this D1.
Moving on:
dateadd(mm, DATEPART(MONTH, GP_DATE) - 1, 0)
is taking the month of GP_DATE, subtracting 1 from it and adding that number of months to the date 0 (1900-01-01). The result is a the 1st of whichever month GP_DATE is in, but in 1900. Let's call this D2.
When we add D1 and D2 together, we approximately get a date of the 1st of whichever month GP_DATE is in, in either this year or next year. Note, however, that this goes wrong if the D1 year is a leap year, we get it wrong by a day for months after February.
Finally, we take DATEPART(DAY, GP_DATE) - 1, where we take the day of the month from GP_DATE, subtract 1, and add that on to our result so far. This should set the final date to be on the same day of the month as GP_DATE, except for the error mentioned above.
So, it appears that the code is trying to take GP_DATE and get the same date in either this year or next year, depending on how late in the year GP_DATE is. However, it also appears it was never tested with consideration for leap years.
A far more likely correct version of this query would be this instead:
SELECT
DATEADD(year,
DATEDIFF(year,GP_DATE,CURRENT_TIMESTAMP) +
CASE WHEN DATEPART(month,GP_DATE)>10 THEN 0 ELSE 1 END
,GP_DATE)

Fiscal Year from Current Date

I'm using SSMS/SSRS2012 working on report to capture all hours worked in the current fiscal year, which for this purpose is Oct 1-Sep 30.
I'm looking for a case statement that says the following:
if the current month < 10 (october) then #FYStart = last year
if the current month >= 10 then #FYStart = current year
When I query SELECT GETDATE() here is the format: 2020-06-16 15:24:57.637
I have tried the following, but it only half works.
SELECT CASE WHEN DATEPART(MONTH,(CAST(getdate() AS INT)))>09
THEN YEAR(CAST(getdate() AS INT))
ELSE DATEADD(YEAR,-1,(CAST(getdate() AS INT)))
END
The result from this gives me 2019-06-17 00:00:00.000 which is a step in the right direction, but if I change the month to a month that has already passed,
SELECT CASE WHEN DATEPART(MONTH,(CAST(getdate() AS INT)))>03
THEN YEAR(CAST(getdate() AS INT))
ELSE DATEADD(YEAR,-1,(CAST(getdate() AS INT)))
END
I get this result: 1905-07-14 00:00:00.000
Something is obviously going wrong here but I'm not sure what exactly. I'm thinking it's something with the data types but I'm not sure what to check/where to start.
So from what I gather, you are trying to isolate the year (as an integer) from today's date and store it in #FYStart. If today's date is before October, you want to assign it to last year, and if it's October or later, assign it to this year, correct?
If so, try this:
DECLARE #FYStart int
SET #FYStart = (
SELECT CASE WHEN DATEPART(MONTH, GETDATE()) < 10
THEN DATEPART(YEAR, DATEADD(YEAR, -1, GETDATE())) -- last year
ELSE DATEPART(YEAR, GETDATE()) -- this year
END
)
Unless I'm overlooking something, is it not just something as simple as...
SELECT CASE WHEN MONTH(getdate()) <10
THEN YEAR(getdate()) -1
ELSE YEAR(getdate())
END

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;