Find rows where ID matches and date is within X days - mysql

Somewhat new to SQL and I'm running into a bit of issue with a project. I have a table like this:
ID
subscription_ID
renewal_date
1
11
2022-01-01 00:00:00
2
11
2022-01-02 00:00:00
3
12
2022-01-01 00:00:00
4
12
2022-01-01 12:00:00
5
13
2022-01-01 12:00:00
6
13
2022-01-03 12:00:00
My goal is to return rows where the subscription_ID matches and the start_date is within or equal to a certain # of days (hours would work as well). For instance, I'd like rows where subscription_ID matches and the start_date is within or equal to 1 day such that my results from the table above would be:
ID
subscription_ID
renewal_date
1
11
2022-01-01 00:00:00
2
11
2022-01-02 00:00:00
3
12
2022-01-01 00:00:00
4
12
2022-01-01 12:00:00
Any assistance would be greatly appreciated--thanks!

If I understand correctly maybe you are trying something like:
select t.*
from test_tbl t
join ( SELECT subscription_id
, MAX(diff) max_diff
FROM
( SELECT x.subscription_id
, DATEDIFF(MIN(y.start_date),x.start_date) diff
FROM test_tbl x
JOIN test_tbl y ON y.subscription_id = x.subscription_id
AND y.start_date > x.start_date
GROUP BY x.subscription_id , x.start_date
) z
GROUP BY subscription_id
) as t1 on t.subscription_id=t1.subscription_id
where t1.max_diff<=1;
Result:
id subscription_id start_date
1 11 2022-01-01 00:00:00
2 11 2022-01-02 00:00:00
3 12 2022-01-01 00:00:00
4 12 2022-01-01 12:00:00
The subquery returns:
subscription_id max_diff
11 1
12 0
13 2
which is used on the where condition.
Demo

Related

Mysql join on date range

I have a calendar table that looks like this:ยจ
calendar_date
2022-01-01
2022-01-02
2022-01-03
2022-01-04
And another table that has a date_from, and a date to field. If date_to is empty, that row is valid until a more recent date appears.
date_from
date_to
value
2022-01-01
null
1
2022-01-04
2022-01-05
2
2022-01-07
null
3
My expected result is the following:
calendar_date
value
2022-01-01
1
2022-01-02
1
2022-01-03
1
2022-01-04
2
2022-01-05
2
2022-01-06
1
2022-01-07
3
I've tried joining the tables on date_between but it leaves a gap between when 2 ends and 3 begins... This is my query so far:
select
c.calendar_date, v.value
from calendar c
left join values v
on v.start_date <= c.calendar_date
and (
c.calendar_date between v.start_date
and ifnull(
v.stop_date,
ifnull(
(
select min(v2.start_date)
from values v2
where v2.start_date > v.start_date
),
date_add(curdate(), interval 2 year)
)
)
)
Like this:
calendar_date
value
2022-01-01
1
2022-01-02
1
2022-01-03
1
2022-01-04
2
2022-01-05
2
2022-01-06
null
2022-01-07
3

how do i get the correct id with the query results

I want to create a stored procedure in MySQL, but first, I want to get the query right. However, I keep getting the problem that I can't seem to get the correct id back from my query that correspond with the DateTime stamps that I get back.
this is the table I am trying to get the result from:
id EventId start end
1 1 2019-04-05 00:00:00 2019-04-07 00:00:00
2 2 2020-04-03 00:00:00 2020-04-03 00:00:00
3 3 2020-04-02 00:00:00 2020-04-02 00:00:00
7 1 2020-06-11 00:00:00 2020-06-11 00:00:00
9 2 2020-06-18 00:00:00 2020-06-18 00:00:00
10 3 2020-06-11 00:00:00 2020-06-11 00:00:00
11 3 2020-06-07 00:00:00 2020-06-07 00:00:00
query:
SELECT DISTINCT Eventid, MIN(start), id
from date_planning
WHERE `start` >= NOW()
GROUP BY Eventid
this gives me the following result
EventId Min(start) id
1 2020-06-11 00:00:00 3
2 2020-06-18 00:00:00 9
3 2020-06-07 00:00:00 10
but these are the correct ids that belong to those DateTimes:
EventId Min(start) id
1 2020-06-11 00:00:00 7
2 2020-06-18 00:00:00 9
3 2020-06-07 00:00:00 11
You want the row with the minimum "future" date for each eventId. To solve this greatest-n-per-group problem, you need to filter rather than aggregate. Here is one option using a correlated subquery:
select dt.*
from date_planning dt
where dt.start = (
select min(dt1.start)
from date_planning dt1
where dt1.eventId = dt.eventId and dt1.start >= now()
)
For performance, you need an index on (eventId, start).

Get report of last week of all days including days with 0 count

I am trying to get a report of last week entries/tickets and show 0 if that day there was none entries and then show it in google line chart for a project.MySQL table look like this
----------------------------------
id body timeSent
----------------------------------
1 someText 2020-02-29 15:48:18
2 someText 2020-03-02 11:32:07
3 someText 2020-03-02 11:32:07
4 someText 2020-03-04 12:11:13
5 someText 2020-03-05 09:32:09
----------------------------------
I wrote query like this
SELECT count(*) as count_tickets,
substr(timeSent,1,10) AS datetime
FROM tableName
WHERE substr(timeSent,1,10) >= DATE(NOW()) - INTERVAL 7 DAY
GROUP BY substr(timeSent,1,10)
ORDER BY timeSent
Output look like this
----------------------------------
count_tickets dateTime
----------------------------------
1 2020-02-29
2 2020-03-02
1 2020-03-04
1 2020-03-05
----------------------------------
What my required output is
----------------------------------
count_tickets dateTime
----------------------------------
1 2020-02-29
0 2020-03-01
2 2020-03-02
0 2020-03-03
1 2020-03-04
1 2020-03-05
0 2020-03-06
----------------------------------
How can I achieve this?
For just 7 days, one method is to use a derived table of numbers, and left join it with the original table:
select
count(t.timesent) as count_tickets,
current_date - interval x.n day as datetime
from (
select 0 n union all select 1 union all select 2 union all select 3
union all select 4 union all select 5 union all select 6
) x
left join tablename t
on t.timesent >= current_date - interval x.n day
and t.timesent < current_date - interval (x.n - 1) day
group by x.n
order by x.n desc
Demo on DB Fiddle:
count_tickets | datetime
------------: | :---------
1 | 2020-02-29
0 | 2020-03-01
2 | 2020-03-02
0 | 2020-03-03
1 | 2020-03-04
1 | 2020-03-05
0 | 2020-03-06

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

Select the 2 latest records from table

I have data like in this mysql table:
id customer_id date price
1 A 2014-01-01 4
2 A 2014-02-01 3
3 B 2014-03-01 2.5
4 B 2014-04-01 1
5 B 2014-05-01 5
6 C 2014-06-01 2
7 D 2014-07-01 2
8 D 2014-08-01 2.5
9 D 2014-09-01 1
I want to get the latest two dates for customer_id A, B and D. My result should be like this:
id customer_id date price
1 A 2014-01-01 4
2 A 2014-02-01 3
4 B 2014-04-01 1
5 B 2014-05-01 5
8 D 2014-08-01 2.5
9 D 2014-09-01 1
Any help is greatly appreciated.
One possible way :
SELECT *
FROM test s
WHERE (
SELECT COUNT(*)
FROM test f
WHERE f.customer_id = s.customer_id AND
f.`date` >= s.`date`
) <= 2
AND customer_id in('A','B','D');
[SQL Fiddle demo]
Try like this
select * from table where customer_id in('A','B','D') order by date desc limit 2