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.
Related
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
id start_date interval period
1 1/22/2018 2 month
2 2/25/2018 3 week
3 11/24/2017 3 day
4 7/22/2017 1 year
5 2/25/2018 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). 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.
Here what i have done to resolve this. I am using mysql 5.7. I found ways 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 and its a performance killer and there is restriction of population of records.(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(in oracle)
select id
from (select a.*,
case
when period='week'
then mod((to_date('22-07-2018','dd-mm-yyyy')-start_date),7*interval)
when period='month' and to_char(to_date('22-07-2018','dd-mm-yyyy'),'dd')=to_char(start_date,'dd')
and mod(months_between(to_date('22-07-2018','dd-mm-yyyy'),start_date),interval)=0
then 0
when period='year' and to_char(to_date('22-07-2018','dd-mm-yyyy'),'dd-mm')=to_char(start_date,'dd-mm')
and mod(months_between(to_date('22-07-2018','dd-mm-yyyy'),start_date)/12,interval)=0
then 0
when period='day'
and mod((to_date('22-07-2018','dd-mm-yyyy')-start_date),interval)=0
then 0 else 1 end filter from kml_subs a)
where filter=0;
But I need to do this for a period of dates not a single date. Any suggestions or solutions will be much appreciated.
Thanks,
Kannan
Assuming this is an Oracle question and not MySQL:
I think the first thing that you need to do is calculate when the due date is. I think a simple case statement can handle that for you:
case when period = 'day' then start_date + numtodsinterval(interval,period)
when period = 'week' then start_date + numtodsinterval(interval*7,'day')
when period = 'month' then add_months(start_date,interval)
when period = 'year' then add_months(start_date,interval*12)
end due_date
Then, using that new due_date field, you can check if the due date falls between the desired date range.
select *
from(
select id,
start_date,
interval,
period,
case when period = 'day' then start_date + numtodsinterval(interval,period)
when period = 'week' then start_date + numtodsinterval(interval*7,'day')
when period = 'month' then add_months(start_date,interval)
when period = 'year' then add_months(start_date,interval*12)
else null end due_date
from data)
where due_date between date '2018-02-25' and date '2018-03-12'
The above query checking between 2/25/18 and 3/12/18 produces the following output using your data:
+----+-------------+----------+--------+-------------+
| id | start_date | interval | period | due_date |
+----+-------------+----------+--------+-------------+
| 2 | 05-FEB-2018 | 3 | week | 26-FEB-2018 |
| 5 | 25-FEB-2018 | 2 | week | 11-MAR-2018 |
+----+-------------+----------+--------+-------------+
i have table for structure like this
empid fromdate todate office_ID
1 2012-03-01 2014-04-2 1
1 2014-04-03 ---- 2
2 2012-03-01 2014-04-2 2
3 2012-03-01 2014-04-2 1
from this table i want to fetch that at some month
for ex. for may 205 where was employee 1
for that i have designed query
select* from tbl_emp_office where (year(From_date)*100+ month(From_date)) < '201505'
but it is not giving correct answer for all users
if employee currently working at some office then todate will be not known hence it is null (this logic can be changed if you suggest some better )
If I understand you correctly, you want this:
select office_id
from employee_history
where year(fromdate) <= 2015
and month(fromdate) <= 5
and (
(month(todate) >= 5 and year(todate) >= 2015)
or todate is null
)
and empid = 1;
The query uses mysql functions to break the dates into year and month, and then makes sure that the month and year you are looking for is equal to or after their startdate, and that their todate is either null, or occurs after the month/year combo you are looking for.
This should also include offices they were in for a partial month.
I'm working on a query to get records based on two dates, start and end dates.
What I need to obtain are records that are span some or all of the given period, in other words the start date maybe before the parameter date but less than the end date or start after the start date and end after the end date.
I.e. Start date = 01 Oct 12 and end date 31 Oct 12. I would like to capture records where start date is before 1 Oct but spans this period whether it finishes in November or mid October. As well as records that are between 01 Oct 12 and 31 Oct 12.
In reality I need the records that exclude this period, but first need to make sure I'm getting this dataset correct.
I'm starting with this simple data set stored in MyTable, with both start_date and end_date as Date/Time data type.
id start_date end_date
1 9/29/2012 9/30/2012
2 9/29/2012 10/2/2012
3 9/29/2012 11/1/2012
4 10/2/2012 11/1/2012
5 11/1/2012 11/2/2012
Running the query below, and supplying 2012-10-01 and 2012-10-31 for the range_start and range_end parameters, gives me this output result set.
id start_date end_date
2 9/29/2012 10/2/2012
3 9/29/2012 11/1/2012
4 10/2/2012 11/1/2012
If this is not similar to what you wanted, please edit your question to show us a brief sample set of input data and the output you want from that sample.
Also, note the time components of my start_date and end_date values were all midnight. If your counterparts include any other times of day, you will need to revise the query to deal with them.
This is the SQL from the query I used:
PARAMETERS range_start DateTime, range_end DateTime;
SELECT m.id, m.start_date, m.end_date
FROM MyTable AS m
WHERE
m.start_date Between [range_start] And [range_end]
OR m.end_date Between [range_start] And [range_end]
OR (m.start_date<[range_start] AND m.end_date>[range_end]);
I'm trying to get my code to output in the following format:
january 2012 - 34
february 2012 - 23
where 34 and 23 would be a count of the total rows that fall within that month that have the id_dealership of 7. I need this to output all data for every month that an assignment was ever made.
The assignments table structure is as follows:
id_dealer (int)
date_assigned (int)
I've tried this but it does not work at all:
SELECT MONTH(date_assigned), YEAR(date_assigned), COUNT(*)
FROM assignments
GROUP BY MONTH(date_assigned), YEAR(date_assigned)
SELECT
MONTH(FROM_UNIXTIME(date_assigned)),
YEAR(FROM_UNIXTIME(date_assigned)),
COUNT(*)
FROM assignments
GROUP BY
MONTH(FROM_UNIXTIME(date_assigned)),
YEAR(FROM_UNIXTIME(date_assigned))
Your date_assigned column should be of type DATE. AFAIK MONTH works on date columns
and if you want the month name from a DATE column use : MONTHNAME(date_assigned)
try this query
SELECT
MONTH(FROM_UNIXTIME(date_assigned)),
YEAR(FROM_UNIXTIME(date_assigned)),
COUNT(*)
FROM assignments
GROUP BY 1,2
For people who would like to output a DATETIME rather than a month/year combo, here's another way to solve the problem. The benefit of using DATETIME is that it can easily be plugged into data visualization libraries and tools.
SELECT
LAST_DAY(FROM_UNIXTIME(date_assigned)),
COUNT(*)
FROM assignments
GROUP BY 1
ORDER BY 1 DESC
The LAST_DAY() function returns the last day of the month for a given DATE or DATETIME value. If you'd rather grab the first day, you could select this instead: ADDDATE(LAST_DAY(SUBDATE(FROM_UNIXTIME(date_assigned), INTERVAL 1 MONTH)), 1). It adds a day to the last date then subtracts a month.
The 1 values are column position integers -- shorthand so we don't have to type LAST_DAY(FROM_UNIXTIME(date_assigned)) any more than we need to (they start at 1, not 0).
Example output:
|-------------------------------------------|------------------|
| LAST_DAY(FROM_UNIXTIME(date_assigned)) | COUNT(*) |
|-------------------------------------------|------------------|
| September 30, 2020, 12:00 AM | 34 |
|-------------------------------------------|------------------|
| August 31, 2020, 12:00 AM | 23 |
|-------------------------------------------|------------------|