How do I select only the month end date from a table - sql

I am new to SQL, here is my problem.
I have a table with daily dates:
Date:
20190101
20190102
20190103
.
**20190131**
20190201
20190202
20190203
.
**20190228**
20190301
20190302
20190303
.
**20190331**
I want to select only the month-end dates, what would be the code to do that?
thanks
I am using MS SQL Studio.

One method in standard SQL would be:
select t.*
from t
where extract(month from date + interval '1' day) <> extract(month from date);
Date/time functions vary significantly by database, so the exact functions might not match your database. However, the idea is simple: add one day and see if the month changes.

In standard SQL, you could do:
select date
from mytable
where date = date_trunc('month', date) + interval '1' month - interval '1' day
Edit
In SQL Server, you can just use eomonth(). Given a date, this functions returns the corresponding end of month, which you can compare against the date. So:
select date
from mytable
where date = eomonth(date)

Related

How to make POSTGRESQL query based on first 2 parameters and latest third parameter

I have DB:
**client_id | Version | Date(year, month, day)**
I need to make query request for last year(or last 12 months) group by Client_id, Version and latest date(!) for them.
For example:
client_id | Version | **LATEST** Date
23 v2 2022-1-25
23 v1 2021-3-23
25 v0 2021-6-23
This is what I have right now:
SELECT client_id, Version, Date
FROM db_table
WHERE date >= '2022-01-01' AND date < NOW()::DATE
GROUP BY client_id, Version, Date
And I'm getting result for EVERY DAY. If I'm removing DATE from group by, its complaining that Date should be in Group by.
I hope I did describe everything properly. I'm new here, so please let me know if I provide not full info.
Thank you for your time.
To get the most recent full year (i.e. not including the partial current day),
SELECT current_date - interval '1 year'; --this returns 2021-02-07 when run today
To consider today as part of the 12 month period, then:
SELECT current_date - interval '1 year - 1 day'; --this returns 2021-02-08 when run today
So, assuming that you want the former option (you can switch it if you like):
SELECT client_id, "Version", MAX("Date") AS latest_date
FROM db_table
WHERE "Date" BETWEEN current_date - interval '1 year' AND current_date
GROUP BY client_id, "Version";
p.s. recommend you don't use "Date" as a column name since it's a reserved word, and avoid using upper case letters in column names :)

How to generate dynamic table having begin month date and end month date Teradata or SAS SQL

I’d like to generate a dynamic Table with the start date of a month as a column and the end date of the month as another column.
Ideally, I’d like to provide two years, f.e. 2016 and 2021. The output I’d like to have when providing these two years is the following:
Begin_of_Month End_of_Month
2016-01-01 2016-01-31
2016-02-01 2016-02-29
.
.
.
2021-12-01 2021-12-31
Kindly note that I require the output for all years from 2016 to 2021. In my example above this would mean that 2017 2018 2019 2020 should be included.
I have tried to play with a time series function of Teradata but failed to get results.
The solution I tried to recreate in Teradata is this one: How to generate calendar table having begin month date and end month Date
Furthermore, I have tried the EXPAND ON PERIOD time series function of Teradata.
I'm sure there are some fancy ways of doing this, but I think just hitting up the built-in calendar table is probably the easiest:
SELECT DISTINCT
min(calendar_date) OVER (PARTITION BY year_of_calendar, month_of_calendar) as start_of_month,
max(calendar_date) OVER (PARTITION BY year_of_calendar, month_of_calendar) as end_of_month
FROM sys_calendar.calendar
WHERE year_of_calendar BETWEEN 2016 and 2021
To do this without a table reference, it gets a little ugly. EXPAND ON seems like an obvious route, but it errors if there is no table reference in the FROM clause. UNION suffers from the same issue, but we can cheat with UNION by using a cte. EXPAND ON is more picky and to trick it we can hijack Teradata's JSON_TABLE feature:
SELECT BEGIN(dt), PRIOR(END(dt))
FROM JSON_TABLE
(
ON (SELECT 1 as id, NEW JSON('{"startdate":"2016-01-01","enddate":"2021-12-31"}') jd)
USING
rowexpr('$')
colexpr('[{"jsonpath" : "$.startdate", "type" : "DATE"},
{"jsonpath" : "$.enddate", "type" : "DATE"}]')
) as jt(id, startdate, enddate)
EXPAND ON PERIOD(startdate, enddate) as dt BY ANCHOR MONTH_BEGIN
You could also go with a recursive CTE to build out the months, which feels less hacky, but takes longer to generate.
WITH startend AS
(
SELECT
DATE '2016-01-01' periodstartdate,
DATE '2021-12-31' AS periodenddate
)
,RECURSIVE months AS
(
SELECT periodstartdate,
periodenddate,
periodstartdate as monthstartdate,
1 as monthoffset
FROM startend
UNION ALL
SELECT periodstartdate,
periodenddate,
ADD_MONTHS(periodstartdate, monthoffset),
monthoffset + 1
FROM
months
WHERE monthoffset < months_between(periodenddate, periodstartdate)
)
SELECT monthstartdate, monthstartdate + INTERVAL '1' MONTH - INTERVAL '1' DAY as monthenddate from months;
I'd be very interested if there is a more elegant way to pull this off. Without dual or sequence generation like are present in other RDBMS, the options to build data sets with no table reference are pretty limited.
Normally EXPAND ON only works when a table is accessed in FROM, but applying some function like TRUNC or TO_DATE fools the optimizer:
WITH dummy AS
(
SELECT
2016 AS yr_start
,2021 as yr_end
,TO_DATE(TRIM(yr_start) || '-01-01') AS pd_start
,TO_DATE(TRIM(yr_end+1) || '-01-01') AS pd_end
)
SELECT
BEGIN(pd) AS Begin_of_Month
,LAST(pd) AS End_of_Month
FROM dummy
EXPAND ON PERIOD(pd_start, pd_end) AS pd
BY INTERVAL '1' MONTH
If you are going to do this in SAS then there is no need for SQL.
data want;
do year=2016 to 2021;
do month=1 to 12;
start_of_month=mdy(month,1,year);
end_of_month=intnx('month',start_of_month,0,'e');
output;
end;
end;
format start_of_month end_of_month yymmdd10.;
drop year month;
run;

SQL to display data of current month & next month from table

I wanted some guidance on producing an SQL query that collects the table information of the current date and also next month without having to type in every day for the current month being October or the next month being November.
Basically I've got a table called WORK, in this table there are SHIFTID, DATEOFSHIFT, and MEMBERSHIPID. I basically need to list the SHIFTID's of shifts where MEMBERSHIPID = null and where DATEOFSHIFT is in November (next month)
Then I need to produce a query for the shift roster showing SHIFTID, DATEOFSHIFT, and MEMBERSHIPID of each shift in this current month.
This is the structure of my database table if needed.
I would recommend:
select w.*
from work w
where w.membershipid is null and
w.dateofshift >= trunc(sysdate, 'Month') + interval '1' month and
w.dateofshift < trunc(sysdate, 'Month') + interval '2' month;
You can also phrase the where as:
where w.membershipid is null and
trunc(w.dateofshift, 'Month') >= trunc(sysdate, 'Month') + interval '1' month
but this makes it hard for Oracle to use an index if an appropriate one is available.
Well from what you've provided, I infer that you want a query to display the information on all those fields for the current month. That is achievable by:
Select SHIFTID, DATEOFSHIFT, MEMBERSHIPID
From WORK
Where Month(DATEOFSHIFT)=MONTH(GETDATE());

Presto SQL get yyyymm minus 2 months

I am using Presto. I have an integer column (let's call the column 'mnth_nbr') showing year and month as: yyyymm. For instance, 201901. I want to have records showing all dates AFTER 201901 as well as 2 months before the given date. In this example, it would return 201811, 201812, 201901, 201902, 201903, etc. Keep in mind that my data type here is integer.
This is what I have so far (I do a self join):
select ...
from table 1 as first_table
left join table 1 as second_table
on first_table.mnth_nbr = second_table.mnth_nbr
where first_table.mnth_nbr <= second_table.mnth_nbr
I know this gives me all dates AFTER 201901, including 201901. But, I don't know how to add the 2 previous months (201811 and 201812)as explained above.
As far as the documentation, Presto DB date_parse function expects a MySQL-like date format specifier.
So the proper condition for your use case should be :
SELECT ...
FROM mytable t
WHERE
date_parse(cast(t.mnth_nbr as varchar), '%Y%m') >= date '2019-01-01' - interval '2' month
Edit
As commented by Piotr, a more optimized expression (index-friendly) would be :
WHERE
mnth_nbr >= date_format(date '2019-01-01' - interval '2', '%Y%m')
Something like this would help. first parse your int to date
date_parse(cast(first_table.mnth_nbr as varchar), 'yyyymm') > date '2019-01-01' - interval '2' month
please keep in mind that you may encounter with indexing issues with this approach.

Convert date into individual numerical columns for year month and day SQL

I have a date column in the format YY-MON-DD, e.g. 25-JUN-05. Is it possible to isolate this into 3 separate columns for year, month and day? Where month is converted from text to numerical, e.g. Year: 25, Month: 06, Day: 05?
MS SQL SERVER
As Nebi suggested, you can use DATEPART and extract each part and store it into different columns.
SELECT DATEPART(DAY,'2008-10-22'); -- Returns DAY part i.e 22
SELECT DATEPART(MONTH,'2008-10-22'); -- Returns MONTH part i.e 10
SELECT DATEPART(YEAR,'2008-10-22'); -- Returns YEAR part i.e 2008
Try with the below script,if you are using SQL Server.
SELECT 'Year: '+CAST(LEFT(YourdateColumn,2) as VARCHAR(2))+', Month: ' +CAST(MONTH('01-'+SUBSTRING(YourdateColumn,4,3)+'-15')as VARCHAR(2))+', Day:'+CAST(RIGHT(YourdateColumn,2)as VARCHAR(2))
FROM Yourtable
sample output :
You didn't specify your DBMS.
The following is standard SQL assuming that column really is a DATE column
select extract(year from the_column) as the_year,
extract(month from the_column) as the_month,
extract(day from the_column) as the_day
from the_table;