MySQL: Join on most recent date - mysql

I have a table containing dates and a value:
table_1
-------
dt x
2018-01-01 1
2018-01-06 4
2018-01-07 2
2018-01-12 3
And I have another table containing dates:
table_2
-------
dt
2018-01-01
2018-01-03
2018-01-04
2018-01-06
2018-01-08
2018-01-09
2018-01-11
I want to create a new table my_joined_table that
contains all dates from table_2 and
for each date, contains the most recent value of table_1.x that is not newer than the date in the given row
So the result should be:
my_joined_table
---------------
dt x
2018-01-01 1
2018-01-03 1
2018-01-04 1
2018-01-06 4
2018-01-08 2
2018-01-09 2
2018-01-11 2
This is probably a standard problem, but I cannot seem to figure it out. Any help is appreciated.

This query will give you the result you want. It JOINs table_2 to table_1 on table_1 having the maximum dt less than or equal to the table_2 dt value:
SELECT t2.dt, t1.x
FROM table_2 t2
JOIN table_1 t1 ON t1.dt = (SELECT MAX(dt) FROM table_1 WHERE table_1.dt <= t2.dt)
Output:
dt x
2018-01-01 1
2018-01-03 1
2018-01-04 1
2018-01-06 4
2018-01-08 2
2018-01-09 2
2018-01-11 2
To create your my_joined_table table, just use a CREATE TABLE ... SELECT query:
CREATE TABLE my_joined_table AS
SELECT t2.dt, t1.x
FROM table_2 t2
JOIN table_1 t1 ON t1.dt = (SELECT MAX(dt) FROM table_1 WHERE table_1.dt <= t2.dt)
Demo on dbfiddle

Related

Select Max and Min datetime for distinct user

I have a record as below
ID(int) DATA_ORA(timestamp) BADGE LETTORE
1 2017-04-01 09:30:00 1 1
2 2017-04-01 12:30:00 1 2
3 2017-04-01 13:30:00 1 1
4 2017-04-01 18:30:00 1 2
5 2017-04-01 09:30:00 2 1
6 2017-04-01 18:30:00 2 2
7 2017-04-02 09:30:00 1 1
8 2017-04-02 18:30:00 1 2
9 2017-04-03 09:30:00 3 1
10 2017-04-03 12:30:00 3 2
11 2017-04-03 13:30:00 3 1
12 2017-04-03 18:30:00 3 2
I want to get the first access time and the last daily logout time (for each day) for each individual user (badge).
How I can do this?
The record I wish to as below
ID(int) DATA_ORA(timestamp) BADGE LETTORE
1 2017-04-01 09:30:00 1 1
4 2017-04-01 18:30:00 1 2
5 2017-04-01 09:30:00 2 1
6 2017-04-01 18:30:00 2 2
7 2017-04-02 09:30:00 1 1
8 2017-04-02 18:30:00 1 2
9 2017-04-03 09:30:00 3 1
12 2017-04-03 18:30:00 3 2
Is it possible to do that? Thanks.
NOTE: ID are auto-incremented and LETTORE 1 is entry and LETTORE 2 is exit.
You can do it grouping by date, badge and lettore like:
SELECT date(DATA_ORA),badge,lettore, case when lettore=1 then min(time(data_ora))
when lettore=2 then max(time(data_ora))
else 0
end
FROM table1
group by date(DATA_ORA),badge,lettore
try below using correlated subquery and union all
select * from tablename a
where DATA_ORA in (select min(DATA_ORA) from tablename b where a.badge=b.badge)
union
select * from tablename a
where DATA_ORA in (select max(DATA_ORA) from tablename b where a.badge=b.badge)
I like #fa06 answer, but he misses, that you want the data daily.
so try this:
select * from t1 a
where DATA_ORA in (select min(DATA_ORA) from t1 b where a.badge=b.badge GROUP BY DATE_FORMAT(DATA_ORA, '%Y%m%d'))
union
select * from t1 a
where DATA_ORA in (select max(DATA_ORA) from t1 b where a.badge=b.badge GROUP BY DATE_FORMAT(DATA_ORA, '%Y%m%d'));
Here is the executed version of your table and query that gives output in the order you needed, on DB-fiddle.
Try this query:
select * from EntryExitLogs where id in
(select id from EntryExitLogs where (badge,data_ora)= any
(select badge,min(data_ora)from EntryExitLogs group by date(data_ora),badge))
union
(select * from EntryExitLogs where id in
(select id from EntryExitLogs where (badge,data_ora)= any
(select badge,max(data_ora)from EntryExitLogs group by date(data_ora),badge)))
order by id;
I think its better to make use of the ID column for selecting the rows, because the timestamp column contains duplicates.
You could use a join with subquery for badge 1 and badge 2
select t1.badge, min_dat, nax_date
from (
select badge, min_(data_ora) min_data
from my_table
where lettore = 1
group by badge
) t1
INNER JOIN (
select badge, max_(data_ora) max_data
from my_table
where lettore = 2
group by badge
) t2 ON t1.badge = t2.badge

MYSQL multiplying result when sum, count and group

I think i need some help with this. Tried different queries million times now but nothing is working. I want it to sum t1.a and count t2.b and show the result but it is multiplying both.
I have tried left joins, right joins, without joins but i think i have not the skills to solve this!
$query ="SELECT t1.date, t1.a, t2.date, t2.b,
SUM(t1.a) AS sum1,
COUNT(t2.b) AS sum2
FROM t1
LEFT JOIN t2
ON t1.date = t2.date
GROUP BY t1.date, t2.date
";
t1:
id date a
1 2019-05-01 5
2 2019-05-01 5
3 2019-05-01 5
4 2019-05-01 1
5 2019-05-01 1
6 2019-05-02 5
7 2019-05-02 5
8 2019-05-02 5
t2:
id date b
1 2019-05-01 d
2 2019-05-01 d
3 2019-05-01 d
4 2019-05-02 d
5 2019-05-02 d
6 2019-05-02 d
7 2019-05-02 d
8 2019-05-02 d
The result is:
2019-05-01 51 15
2019-05-02 75 15
But it should be:
2019-05-01 17 3
2019-05-02 15 5
What i´m doing wrong???
Based on your expected results, you must group each table first and then join them:
SELECT
t1.date, t1.sum1, t2.sum2
FROM (
SELECT t1.date, SUM(t1.a) AS sum1
FROM t1 GROUP BY t1.date
) t1 LEFT JOIN (
SELECT t2.date, COUNT(t2.b) AS sum2
FROM t2 GROUP BY t2.date
) t2
ON t1.date = t2.date
See the demo.
Results:
| date | sum1 | sum2 |
| ---------- | ---- | ---- |
| 2019-05-01 | 17 | 3 |
| 2019-05-02 | 15 | 5 |

Depending on the following, the following information is displayed, otherwise it will not be displayed

condition is: Today value is more than yesterday and yesterday more than the day before if this happened show else not show
select * from mytable where
all records 2018-01-03 2018-01-02 2018-01-01
| > | > |
value value value
in last 3 day and Every day more than the day before
(Today is more than yesterday and yesterday more than the day before if this happened show else not show)
+-----------------------------------+
name date value
-----------------------------
apple 2018-01-03 1000
lg 2018-01-03 2000
sony 2018-01-03 2000
bmw 2018-01-03 3000
apple 2018-01-02 2000
lg 2018-01-02 1000
sony 2018-01-02 2500
bmw 2018-01-02 2000
apple 2018-01-01 500
lg 2018-01-01 500
sony 2018-01-01 3000
bmw 2018-01-01 1000
+-----------------------------------+
I need the following result:
+-----------------------------------+
name date value
-----------------------------
lg 2018-01-03 2000
bmw 2018-01-03 3000
lg 2018-01-02 1000
bmw 2018-01-02 2000
lg 2018-01-01 500
bmw 2018-01-01 1000
+-----------------------------------+
Thanks all
SELECT * FROM mytable where
(date BETWEEN '2018-01-01' AND '2018-01-03')
AND
(name = 'lg' AND name = 'bmw')
SELECT * FROM Mytable WHERE mytable.date> DATEADD(dd,-3,GETDATE())
select name
,date
,value
from
(select t1.name as name
,t1.date as date
,t1. value as value
,t2.value as date_minus_1_value
,t3.value as date_minus_2_value
from mytable t1
inner join mytable t2
on t1.name = t2.name and t1.date = date_add(t2.date,interval -1 day)
inner join mytable t3
on t1.name = t3.name and t1.date = date_add(t3.date,interval -2 day)
)
where (value > date_minus_1_value and date_minus_1_value >
date_minus_2_value)

Mysql find value that follows another

Hard for me to put in a coherent statement but I can give a sample set
ID STATUS DATE
1 A 2016-01-01
2 A 2016-01-01
2 B 2016-01-02
3 C 2016-01-13
4 D 2016-01-14
5 A 2016-01-15
5 B 2016-01-16
6 A 2016-01-17
7 C 2016-01-18
8 B 2016-01-19
9 B 2016-01-20
I want an sql statement that can determine two things:
1) How many items go from STATUS = A to a STATUS = B, with the same ID
2) I only want to show the rows with the aforementioned statuses - as follows:
ID STATUS DATE
2 A 2016-01-01
2 B 2016-01-02
5 A 2016-01-15
5 B 2016-01-16
COUNT(distinct ID) of that result should return 2 in this case
Any help would be appreciated
Join the table with itself, matching rows with the row after them with the same id.
SELECT t1.id, t1.status AS start_status, t1.date AS start_date,
t2.status AS end_status, t2.date AS end_date
FROM yourTable AS t1
JOIN yourTable AS t2 ON t1.id = t2.id AND t1.date = date_sub(t2.date, interval 1 day)
WHERE t1.status = 'A' AND t2.status = 'B'
This will show both rows together, e.g.
id start_status start_date end_status end_date
2 A 2016-01-01 B 2016-01-02
5 A 2016-01-15 B 2016-01-16

Select row of second table only if not exists in first one

I have two tables t1 and t2 with the same structure
id INT
userid INT
date DATETIME
The first table contains my data, while the second table is kind of helper table which contains rows for 10 fix dates and userid = -1
What i need is a SELECT which gives me all rows from t1 with userid=X joined(merged) with all rows from t2 which date is not already in the result of t1.
Pseudo code
SELECT id, date
FROM t1, t2
WHERE (t1.userid=:id OR t2.userid=-1) AND t2.date NOT IN t1.date
Sample:
t1:
id userid date
1 1 2015-12-01
2 1 2015-12-02
3 1 2015-12-03
4 2 2015-12-01
5 2 2015-12-02
t2:
id userid date
1 -1 2015-12-01
2 -1 2015-12-02
3 -1 2015-12-03
4 -1 2015-12-04
5 -1 2015-12-05
Expected output for userid=1:
1 1 2015-12-01
2 1 2015-12-02
3 1 2015-12-03
4 -1 2015-12-04
5 -1 2015-12-05
Thanks for your help
I'll use a union select for doing this.
SELECT
id, date
FROM
t1
WHERE
t1.id=:id
UNION ALL
(SELECT
id, date
FROM
t2
WHERE
t2.id=-1
AND t2.date NOT IN (SELECT date FROM t1 WHERE t1.userid=:id))