I have a data table where data is present for every date (for 50 branches) except saturday and sunday. I am trying to get the last valid date from table from multiple given dates.
select distinct BW_DATE from backdated_weekly where BW_DATE <='2021-09-30' or BW_DATE<='2021-09-26' order by BW_DATE desc;
As 2021-09-30 is a valid date but 2021-09-26 (Sunday) is not present in table. I am trying to get output as
2021-09-30
2021-09-24
But above query gives all results below given dates.
If it is confirmed there are dates continuously in the table for all mon-fri only, simply select the maximum date up to the given date
SELECT MAX(BW_DATE)
FROM backdated_weekly
WHERE BW_DATE <= '2021-09-30'
UNION
SELECT MAX(BW_DATE)
FROM backdated_weekly
WHERE BW_DATE <= '2021-09-26'
Also we can calculate newest date in mon-fri for a given date directly without any table
WEEKDAY is the function to be used
Returns the weekday index for date (0 = Monday, 1 = Tuesday, … 6 =
Sunday).
SELECT CASE WHEN WEEKDAY('2021-09-30') IN ( 5, 6 ) THEN DATE('2021-09-30') - INTERVAL WEEKDAY('2021-09-30') - 4 DAY ELSE DATE('2021-09-30') END
UNION
SELECT CASE WHEN WEEKDAY('2021-09-26') IN ( 5, 6 ) THEN DATE('2021-09-26') - INTERVAL WEEKDAY('2021-09-26') - 4 DAY ELSE DATE('2021-09-26') END
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=477775c0eddbfa733e60bc629a8a68d4
Related
all,
trying to adapt the below query to get this for the last business day of say month may, june or whatever?
select distinct
month(createddate),
year(CreatedDate),
id,
value1,
vaue2,
createddate,
count( distinct id)
from
table
and value2 IN ('harry','sally')
AND createddate > LAST_DAY( '2020-05-21') ## i need last business day here for may.
AND createddate < '2020-06-01' ## i need first day of next month here
group by month(createddate),
year(CreatedDate), id,value1, value2,createddate
ive not used mysql in a while, is there a way i can use a function or stored procedures to find this out? if so how
*** by business day i mean working day, not a weekend***
Presumably, you want to avoid weekend days. So:
(createddate > last_day('2020-05-21') and dayofweek(last_day('2020-05-21') between 2 and 6 or
createddate > last_day('2020-05-21') - interval 1 day and dayofweek(last_day('2020-05-21') = 7 or
createddate > last_day('2020-05-21') - interval 2 day and dayofweek(last_day('2020-05-21') = 1
)
I'm in a situation to write SQL query in MySQL database that dynamically handles populating Financial years.
Financial starts from '01 July' and finishes at '30 June'
When start date and finish date is in the same financial year then for example : '2018-19' with only 1 record
Scenario 1: IF startDate (DD-MM-YYYY format) = 02-07-2018 and FinishDate (DD-MM-YYYY format) = 21-06-2019 then the Financial year will be '2018-19' with only 1 record.
Scenario 2: IF startDate (DD-MM-YYYY format) = 13-07-2018 and FinishDate (DD-MM-YYYY format) = 17-02-2020 then the Financial year will be '2018-19' as record 1 and record 2 as '2019-20'
When the data for startdate and finishdate keeps changing the SQL code should dynamically update the Financial year accordingly.
Input Table Data:
**SQL statements to create some scenario based data.**
CREATE TABLE Test1(
StartDate date,
FinishDate date);
Insert into Test1(StartDate,FinishDate) values ('02-07-2018','21-06-2019');
Insert into Test1(StartDate,FinishDate) values ('13-07-2018','17-02-2020');
Insert into Test1(StartDate,FinishDate) values ('05-05-2018','04-10-2019');
Insert into Test1(StartDate,FinishDate) values ('09-02-2018','21-11-2023');
Select * from Test1;
Expected Output:
Thanks in advance
Swetha
This is actually a multi-part solution. First, you are not even showing a possible Fiscal Calendar to work with. As such, I am dynamically building one. You just need to use a table name for the inner query based on the number of years you want to cover. It can be any table as long as it has that many rows in it. Ex: You want to forecast up to 10 years, the table needs at least 10 rows.
select
#beginFY := date_add( #beginFY, interval 1 year ) BeginFY,
#endFY := date_add( #endFY, interval 1 year ) EndFY,
concat( Date_Format( #beginFY, '%Y' ),'-', Date_Format(#endFY, '%y')) FiscalYear
from
AnyTableWith10Records,
-- basis to START your fiscal years. I am force-setting
-- the beginning and ending to July 1, June 30 respectively
-- but starting 2016
( select #beginFY := '2016-07-01',
#endFY := '2017-06-30' ) sqlvars
limit 10
The above query will create a result set such as
BeginFY EndFY FiscalYear
2017-07-01 2018-06-30 2017-18
2018-07-01 2019-06-30 2018-19
2019-07-01 2020-06-30 2019-20
...
2026-07-01 2027-06-30 2026-27
So at this point, I have every possible fiscal year record, its own begin/end dates for comparison purposes and the formatted fiscal year for representation in your final output.
Now, take that entire query and join to your test table as below.
select
date_format( T.StartDate, '%d-%b-%y' ) StartDate,
date_format( T.FinishDate, '%d-%b-%y' ) FinishDate,
FY.FiscalYear
from
( select
#beginFY := date_add( #beginFY, interval 1 year ) BeginFY,
#endFY := date_add( #endFY, interval 1 year ) EndFY,
concat( Date_Format( #beginFY, '%Y' ),'-', Date_Format(#endFY, '%y')) FiscalYear
from
AnyTableWith10Records,
( select #beginFY := '2016-07-01',
#endFY := '2017-06-30' ) sqlvars
limit 10 ) FY
JOIN test1 T
on ( FY.BeginFY <= T.StartDate AND T.StartDate <= FY.EndFY )
OR ( FY.BeginFY <= T.FinishDate AND T.FinishDate <= FY.EndFY )
OR ( T.StartDate < FY.BeginFY AND FY.EndFY < T.FinishDate )
order by
T.StartDate,
T.FinishDate,
FY.BeginFY
Notice the JOIN condition. I have 3 criteria and any one of them is valid.
1 based on the start date is ANYWHERE within ANY of the fiscal year begin/end dates.
2 based on the finish date is ANYWHERE within ANY of the fiscal year begin/end dates.
3 The fiscal year is COMPLETELY WITHIN the start/finish such as your Feb 9, 2018 through Nov 21, 2023. The 2019-20, 2020-21, 2021-22 and 2022-2023 are ALL completely encompassed within your start/finish and will be included in final output.
For display result, I sorted based on the start date and then the fiscal year it qualified against. You can always tweak it once you get results you are expecting.
I'm working on a project for a Fuel Pump. Here is my table for the records:
I want to display rows from very start (2019-07-03) till the end of the specific month (e.g 2019-09-29) . How could i do achieve this?
A simple WHERE clause will do the trick
SELECT id, date, total_amount, total_paid
FROM table
WHERE date <= LAST_DAY(CURDATE())
CURDATE() will return current date i.e. 2019-09-08
LAST_DAY() will return the last date of current month i.e. 2019-09-30
WHERE clause will return all rows with date <= 2019-09-30
Update
If you want to filter records based on user input which is month and year ( 2019-09 ) then either it can done by appending '-01' at scripting side or using CONCAT at MySQL level,
WHERE date <= LAST_DAY(CONCAT('2019-09', '-01'))
I think this will work. You can change dates accordingly.
Select *
From table
Where date>='2019-07-03' AND date<='2019-09-29'
id start_date interval period
1 2018-01-22 2 month
2 2018-02-25 3 week
3 2017-11-24 3 day
4 2017-07-22 1 year
5 2018-02-25 2 week
the above is my table data sample. start_dates will be expired based on interval and period(i.e id-1 will have due date after 2 months from the start_date, id-2 will have due after 3 weeks vice versa). period is enum of (day,week,month,year). requirement is, Client can give any period of dates. let's say 25-06-2026 to 13-07-2026 like that.. I have to return the ids whose due dates falls under that period.I hope i made my question clear.
I am using mysql 5.7. I found a way to achieve this with recursive CTE's.(not available in mysql 5.7). and there is a way to achieve this by populating virtual records by using inline sub queries along with unions but its a performance killer and we can't do populate virtual records every time a client request comes.(like given in the link Generating a series of dates) I have reached a point to get results for a single date which is very easy. Below is my query.
SELECT b.*
FROM (SELECT a.*,
CASE
WHEN period = 'week' THEN MOD(Datediff('2018-07-22', start_date), 7 * intervals)
WHEN period = 'month'
AND Day('2018-07-22') = Day(start_date)
AND MOD(Period_diff(201807, Extract(YEAR_MONTH FROM start_date)), intervals) = 0 THEN 0
WHEN period = 'year'
AND Day('2018-07-22') = Day(start_date)
AND MOD(Period_diff(201807, Extract(
YEAR_MONTH FROM start_date)) / 12,
intervals) = 0 THEN 0
WHEN period = 'day' THEN MOD(Datediff('2018-07-22', start_date) , intervals)
end filters
FROM kml_subs a)b
WHERE b.filters = 0;
But I need to do this for a period of dates not a single date. Any suggestions or solutions will be much appreciated.
My desired result shoud be like..
if i give two dates.say 2030-05-21 & 2030-05-27. due dates falls under those 6 dates between(2030-05-21 & 2030-05-27) will be shown in the result.
id
1
4
My question is different from Using DATE_ADD with a Column Name as the Interval Value . I am expecting a dynamic way to check due dates based on start_date
Thanks, Kannan
In MySQL, it would seem that a query along these lines would suffice. (Almost) everything else could and should be handled in application level code...
SELECT *
, CASE my_period WHEN 'day' THEN start_date + INTERVAL my_interval DAY
WHEN 'week' THEN start_date + INTERVAL my_interval WEEK
WHEN 'month' THEN start_date + INTERVAL my_interval MONTH
WHEN 'year' THEN start_date + INTERVAL my_interval YEAR
END due_date
FROM my_table;
We have a table that has a StartDate field which holds a type of datetime. There are thousands of records and I am looking for a way to find the number of days within a given result returned from this table. For instance, if my table had this data:
ID | StartDate
--------------
1 01/01/2013 09:34:54
2 01/01/2013 11:23:21
3 04/11/2013 14:43:23
4 04/11/2013 17:13:03
5 04/25/2013 18:02:59
6 07/21/2013 02:56:12
7 10/01/2013 19:43:10
Then the query should return 5 as the 2 dates on 01/01/2013 count as 1 and the same for 04/11/2013.
The only SQL I've been able to come up with is:
SELECT COUNT(DISTINCT(DATEPART(DAY, StartDate)))
FROM Stats
WHERE StartDate BETWEEN '01/01/2013' AND '12/31/2013' --This is just for filtering
But this returns 4 because it doesn't take the month into account.
Any help is appreciated.
You can CAST as date
SELECT COUNT(DISTINCT CAST(StartDate AS DATE))
FROM Stats
WHERE StartDate >= '20130101' AND StartDate < '20140101'
Also use an unambiguous date format such as yyyymmdd and >= < not BETWEEN.
Your current query would include the 31st December if there was a row with exactly the value 20131231 00:00:00 but not any with different times on that date. I doubt that is intentional.