comparison of 2 dates in multiple records - mysql

I have the following table that I would like to compare
I have to compare dates per employee and if the date range is less than 60 days it has to extract the employee.
example:
the employee with number 4 has 3 records (4479,4192,1982)
The combination of these 3 records (4479-4192, 4479-1982, 4192-1982) the dates must be compared and if one of them is less than 60 days, the employee must be extracted.
below the example table:
http://sqlfiddle.com/#!9/b44d4e
id
idEmployee
date
1228
2
2020-06-11 21:10:53
3382
2
2020-06-11 12:37:04
2223
2
2020-08-17 21:10:57
4479
4
2020-08-17 12:37:08
4192
4
2020-07-29 12:37:08
1982
4
2020-07-29 21:10:56
2627
8
2020-04-16 12:37:02
474
8
2020-04-16 21:10:49
1002
10
2020-05-29 21:10:52
3150
10
2020-05-29 12:37:04
pd: mysql database
Any help or suggestion how should I make the query?

Using an exists approach:
SELECT DISTINCT idEmployee
FROM yourTable t1
WHERE EXISTS (SELECT 1 FROM yourTable t2
WHERE t2.idEmployee = t1.idEmployee AND
DATEDIFF(t2.date, t1.date) > 60);
In plain English, the above query says to return any employee record for which we can find another record of the same employee more than 60 days apart. The distinct select removes duplicates.

You can use a self-join
SELECT DISTINCT a.idEmployee
FROM employees AS a
JOIN employees AS b ON a.idEmployee = b.idEmployee AND DATEDIFF(a.date, b.date) > 60
But instead of comparing all with all, you really only need to compare the most extreme dates with each other. If they're less than 60 days apart, all the other dates must also be less.
SELECT idEmployee
FROM employees
GROUP BY idEmployee
HAVING DATEDIFF(MAX(a.date), MIN(a.date)) > 60

one way is to use exists
select * from table t1
where exists (
select 1 from table t2
where t1.idEmployee = t2.idEmployee
and t2.Id <> t1.id
and abs(datediff(t2.date, t1.date)) < 60)

Related

calculate the maximum and minimum number of days between each person's travels

People travel in pairs. How to find the maximum and minimum number of days between trips every user?
People:
id
user
1
Harry
2
George
3
Thomas
4
Jacob
5
Jack
6
Oliver
Travels:
id
date
user1
user2
1
2005-10-03
2
3
2
2005-10-04
1
4
3
2005-10-05
5
6
4
2005-10-06
1
3
5
2005-10-07
2
4
6
2005-10-08
3
5
7
2005-10-10
1
4
8
2005-10-11
5
2
9
2005-10-15
6
4
I tried to solve this problem in the following way, but I still do not understand how to solve this problem:
select People.id,People.user, count(*)
from People
INNER join
(SELECT MIN(TIMESTAMPDIFF(day, t1.date, t2.date)) as mintime,max(TIMESTAMPDIFF(day, t1.date, t2.date))
from Travels as t1
join Travels as t2 on t1.PERSON_1 = t2.PERSON_1
WHERE t1.date< t2.date
GROUP BY t1.PERSON_1) as t3
group by People.id
There is an idea to use the position function to iterate over each user, and then, as a result, look at the dates and find the minimum and maximum, but I still don't understand how to do this
Best is to do it in steps with subqueries, as below (comments are in the query):
select user, max(dateDiff)
from (
select
user,
-- get the diff between previous and current row date to get diff between trips
datediff(date, lag(date) over (partition by user order by date)) dateDiff
from (
-- full flat list of all users and trip dates
select date, user1 `user`
from testtbl
union all
select date, user2
from testtbl
) a
) a group by user
SQL fiddle
Note that I used windowed function which are not avaiable in MySql 5 and below.

How to join two table with where between condition

I have two table name income and expenses. I want to join two table and get the data between the two date ranges value.
Income
=============
id income_name income_price income_date
1 admission 30 2017-10-10
2 hostel 40 2017-10-9
3 bus 50 2017-10-7
expenses
=============
id expenses_name expenses_price expenses_date
1 furniture 30 2017-10-9
2 teacher 40 2017-10-8
3 bus 60 2017-10-7
I want to retrieve the data from two table between the date 2017-10-6 to 2017-10-10.please help me.
Result Table
=============
id income_name income_price expense_name expenses_price
1 admission 30 furniture 30
2 hostel 40 teacher 40
3 bus 50 bus 60
You can use the union operator to merge the result set of two or more queries
Select * from income where (date between 'your_start_date' and 'your_end_date')
UNION
Select * from expenses where (date between 'your_start_date' and 'your_end_date')
The UNION operator selects only distinct values by default. To allow duplicate values, use UNION ALL
Use union all to join result sets of the 2 tables from where you are getting the data. Below is the query.
select *
from Income
where date between '2017-10-6' and '2017-10-10'
union all
select *
from expenses
where date between '2017-10-6' and '2017-10-10';

Select only rows with matching pair

I have a MySQL table as below
ID SHEET_NUMBER DAYS RESULT
1 55201 9 10
2 55209 28 25.5
3 55209 28 27.9
4 38558 7 12
5 38552 5 19
6 38559 5 5
I want to select only rows with firstly matching sheet numbers & only if there if there is a matching pair of 28 days specimens
so if there is only one 28 day it will select nothing but if there is at least 2x 28 day it will get both rows
I'm totally lost, i know i should be using group by.. but i'm unsure of its use.
thankyou
Can you try the following query:
SELECT *
FROM test
WHERE sheet_number IN (
SELECT sheet_number
FROM test
WHERE days = 28
GROUP BY sheet_number
HAVING COUNT(*) >= 2
);
Here's the SQL Fiddle.
First, write a query that finds sheet_number with two or more rows with days value of 28.
SELECT d.sheet_number
FROM my_table_below d
WHERE d.days = 28
GROUP BY d.sheet_number
HAVING COUNT(1) > 1
With that query, we can use that as an inline view, and join back to the original table to find the matching rows:
SELECT t.*
FROM ( SELECT d.sheet_number
FROM my_table_below d
WHERE d.days = 28
GROUP BY d.sheet_number
HAVING COUNT(1) > 1
) m
JOIN my_table_below t
ON t.sheet_number = m.sheet_number
AND t.days = 28
ORDER BY t.sheet_number, t.id
Omit the condition t.days = 28 on the outer query, if the specification is to return all of the rows for the sheet_number, not just the rows with days=28. (The specification is a bit unclear.)

MySQL Group by week num w/ multiple date column

I have a table with columns similar to below , but with about 30 date columns and 500+ records
id | forcast_date | actual_date
1 10/01/2013 12/01/2013
2 03/01/2013 06/01/2013
3 05/01/2013 05/01/2013
4 10/01/2013 09/01/2013
and what I need to do is get a query with output similar to
week_no | count_forcast | count_actual
1 4 6
2 5 7
3 2 1
etc
My query is
SELECT weekofyear(forcast_date) as week_num,
COUNT(forcast_date) AS count_forcast ,
COUNT(actual_date) AS count_actual
FROM
table
GROUP BY
week_num
but what I am getting is the forcast_date counts repeated in each column, i.e.
week_no | count_forcast | count_actual
1 4 4
2 5 5
3 2 2
Can any one please tell me the best way to formulate the query to get what I need??
Thanks
try:
SELECT weekofyear(forcast_date) AS week_forcast,
COUNT(forcast_date) AS count_forcast, t2.count_actual
FROM
t t1 LEFT JOIN (
SELECT weekofyear(actual_date) AS week_actual,
COUNT(forcast_date) AS count_actual
FROM t
GROUP BY weekOfYear(actual_date)
) AS t2 ON weekofyear(forcast_date)=week_actual
GROUP BY
weekofyear(forcast_date), t2.count_actual
sqlFiddle
You have to write about 30 (your date columns) left join, and the requirement is that your first date column shouldn'd have empty week (with a count of 0) or the joins will miss.
Try:
SELECT WeekInYear, ForecastCount, ActualCount
FROM ( SELECT A.WeekInYear, A.ForecastCount, B.ActualCount FROM (
SELECT weekofyear(forecast_date) as WeekInYear,
COUNT(forecast_date) as ForecastCount, 0 as ActualCount
FROM TableWeeks
GROUP BY weekofyear(forecast_date)
) A
INNER JOIN
( SELECT * FROM
(
SELECT weekofyear(forecast_date) as WeekInYear,
0 as ForecastCount, COUNT(actual_date) as ActualCount
FROM TableWeeks
GROUP BY weekofyear(actual_date)
) ActualTable ) B
ON A.WeekInYear = B.WeekInYear)
AllTable
GROUP BY WeekInYear;
Here's my Fiddle Demo
Just in case someone else comes along with the same question:
Instead of trying to use some amazing query, I ended up creating an array of date_columns_names and a loop in the program that was calling this query, and for each date_column_name, performing teh asme query. It is a bit slower, but it does work

How to fetch the most recent timestamped record for the same id from MySQL table? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Fetch the row which has the Max value for a column
I have an audit table of people and the number of shares they own at a particular timestamp. How do I fetch the most recent record for a given id?
mysql audit table
id name shares dateadded
1 Abc 12 2012-10-06 12:18:21
2 Klm 23 2012-10-06 12:18:21
3 Jim 45 2012-10-06 12:18:21
1 Abc 35 2012-11-06 12:18:21
1 Abc 65 2012-11-17 12:18:21
2 Klm 13 2012-11-06 12:18:21
My desired output :
id name shares dateadded
1 Abc 65 2012-11-17 12:18:21
2 Klm 13 2012-11-06 12:18:21
3 Jim 45 2012-10-06 12:18:21
I could do something like this :
select a.* from audittable a join audittable b
on a.id = b.id
where a.dateadded > b.dateadded;
But that gives me only those most recent records that are repeating. In this case ids 1,2 and not 3. How to get a list of most recent records for all IDs without sub-queries or temp tables?
You will need a subquery, however not subselects (which have a very negative performance hit).
JOIN against a subquery which returns the id and MAX(dateadded) aggregate. The subquery join is needed to be able to match all the other column values in the row containing the latest timestamp.
SELECT
audittable.id,
name,
shares,
audittable.dateadded
FROM
audittable
/* Subquery returns id dateadded grouped by id */
JOIN (
SELECT id, MAX(dateadded) AS dateadded FROM audittable GROUP BY id
/* JOIN condition is on both id and dateadded between the two tables */
) maxtimestamp ON audittable.id = maxtimestamp.id AND audittable.dateadded = maxtimestamp.dateadded
Here is a demonstration on SQLfiddle
Without subqueries, you are limited to this
SELECT id, MAX(dateAdded)
FROM audittable
GROUP BY id
If you want the other columns, you need a subquery like Michael Berkowski's answer