Select last entry for every user from log table - mysql

Hello I have problem with sql that is suppose to select last log entry per user for many users.
This is sample how my table looks like
user_id | date
--------------------
1 2013-03-06 10:00:00
17 2013-03-06 11:00:00
2 2013-03-06 10:00:00
5 2013-03-06 10:00:00
1 2013-03-06 11:00:00
17 2013-03-06 13:00:00
17 2013-03-06 13:01:00
2 2013-03-06 14:01:00
2 2013-03-06 15:00:00
2 2013-03-06 18:01:00
The result of this query is suppose to be
user_id | date
--------------------
1 2013-03-06 11:00:00
2 2013-03-06 18:01:00
5 2013-03-06 10:00:00
17 2013-03-06 13:01:00
For now I'm using this query
SELECT
a.user_id,
(SELECT b.date FROM alerts.alerts_log as b WHERE b.user_id = a.user_id ORDER BY b.date DESC LIMIT 1) as date
FROM
alerts.alerts_log as a
WHERE
a.user_id IN (1,2,5,17)
GROUP BY a.user_id
but I dont thiknk its the best one because will be too slow for many records...
can you pls suggest me better one

SELECT user_id , MAX(date)
FROM alerts.alerts_log
GROUP BY user_id;

if you have only two columns in the table, the query below will suffice your needs,
SELECT user_ID, MAX(date) max_date
FROM tableName
GROUP BY user_ID
SQLFiddle Demo
but if not and you want to get all columns within the row, you need to have subquery which separately gets the maximum date per user_ID.
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT user_ID, MAX(date) max_date
FROM tableName
GROUP BY user_ID
) b ON a.user_ID = b.user_ID AND
a.date = b.max_date
SQLFiddle Demo

Related

Want to generate a row_number variable in MySQL 5.6 - but not using #variables

I have a table (all code is on fiddle).
id nom bal bal_dt val_dt
1 Bill 75.00 2019-11-01 2020-03-31
1 Bill 100.00 2020-04-01 2020-07-31
1 Bill 500.00 2020-08-01 2021-11-11 -- record goes over New Year 2021
2 Ben 5.00 2019-11-01 2020-03-31
2 Ben 10.00 2020-04-01 2020-07-31
2 Ben 100.00 2020-08-01 2021-11-11 -- record goes over New Year 2021
6 rows
The primary key is (id, bal_dt) - only one deposit/day.
I want to get the last record before the New Year 2021 (or <= 2021-01-01 00:00:00).
I try code from here as follow.
select a2.id, a2.nom, a2.val_dt,
(select count(*) from account a1 where a1.id < a2.id) AS rn
from account a2
where a2.val_dt <= '2021-01-01 00:00:00'
order by val_dt desc;
But result is not good.
id nom val_dt rn
1 Bill 2020-07-31 0
2 Ben 2020-07-31 3
1 Bill 2020-03-31 0
2 Ben 2020-03-31 3
I want something like
id nom rn val_dt bal
1 Bill 1 2020-08-01 500.00
2 Ben 1 2020-08-01 100.00
so I choose record for Bill and Ben. Any helps please?
note - I don't requier #variables and not assume 3 only records or only 2 accounts and not same dates and not only last date!
You can use NOT EXISTS and a correlated subquery that checks for the absence of a younger timestamp within the desired period.
SELECT a1.id,
a1.nom,
a1.val_dt
FROM account a1
WHERE a1.val_dt < '2021-01-01 00:00:00'
AND NOT EXISTS (SELECT *
FROM account a2
WHERE a2.val_dt < '2021-01-01 00:00:00'
AND a2.val_dt > a1.val_dt
AND a2.id = a1.id);
Note that 2021-01-01 00:00:00 already is in 2021, so the operator needs to actually be < not <=.
Solved it (see fiddle)!
select
tab.id, tab.md, a2.bal
from account a2
join
(
select
a1.id, max(a1.bal_dt) AS md
from account a1
where a1.bal_dt <= '2021-01-01 00:00:00'
group by a1.id
) as tab
on a2.id = tab.id and a2.bal_dt = tab.md;
and.
id md bal
1 2020-08-01 500.00
2 2020-08-01 100.00

How to get total appointment durations from this table using sql

I have 3 mysql tables:
appointments
id slot_id patient_name doctor_id deleted_at
1 11 Tasin 23 2019-10-10
2 12 Nawaz 22 null
3 13 Rakib 23 null
4 14 Hossen 23 null
5 15 Aritra 24 null
6 16 Anik 22 null
7 17 Manik 22 null
doctors
id status doctor_name
22 1 Khaled
23 1 Hasan
24 0 Rumi
slots
id date duration time
11 2019-10-10 2900 01:01
12 2019-10-11 1200 02:01
13 2019-10-18 1100 03:01
14 2019-09-08 200 11:01
15 2019-08-01 500 01:31
16 2019-10-07 300 02:31
17 2019-10-02 1200 03:31
Now, I want to show a list of doctors with their total appointment durations in decreasing order using SQL query.
Unfortunately, I don't have any idea about this SQL query. Can you assist me?
SELECT DOCTOR_NAME, SUM(DURATION) FROM APPOINTMENTS A
JOIN DOCTORS D ON D.ID = A.DOCTOR_ID
JOIN SLOTS S ON S.ID = A.SLOT_ID
GROUP BY D.ID, DOCTOR_NAME
ORDER BY SUM(DURATION) DESC;
select d.doctor_id, d.doctor_name, sum(apt.duration) as total_duration from
doctors as d
join appointments as apt on apt.doctor_id = d.doctor_id
join slots as s on s.id = apt.slot_id
group by d.doctor_id, d.doctor_name
The above query should work fine.
There might be some typo as I didn't write it in the SQL management studio.

How to get difference based on date in mysql

I have like below mentioned two table:
Table1
ID Unique_Value
T-1 OI-45
T-4 OI-45
T-8 OI-45
T-7 OI-46
T-6 OI-49
Table2
ID Date Value
T-1 2018-01-01 15:13:22 10
T-4 2018-03-15 18:10:45 15
T-8 2018-05-12 05:17:43 25
T-7 2018-04-01 15:13:22 12
T-6 2018-06-01 15:13:22 18
I have joined the Table2 ID with Table1 ID and get the Unique_Value, based on the unique value and order by Date in Descending order and group by Unique_Value, I want to get the difference value of a particular ID from the previous Value.
Required Output would be:
ID Date Value Unique_Value Difference
T-1 2018-01-01 15:13:22 10 OI-45 [Null]
T-4 2018-03-15 18:10:45 15 OI-45 5
T-8 2018-05-12 05:17:43 25 OI-45 10
T-7 2018-04-01 15:13:22 12 OI-46 [Null]
T-6 2018-06-01 15:13:22 18 OI-49 [Null]
I have tried using Lead Log but it didn't worked.
You can try below using lag() function - it will work for mysql version 8.0+
DEMO
select id,Date,value,Unique_Value,case when prevval is null then null else value-prevval end as Difference
from
(
select t1.Id,t1.Unique_Value,t2.Date,t2.value,lag(t2.value,1) over(partition by t1.Unique_Value order by t2.Date) as prevval
from table1 t1 inner join table2 t2 on t1.id=t2.id
)A
For Mysql Version 5.7 you can try below -
DEMO
SET #quot=0, #latest=0, #comp=''
select id, Unique_Value,d,value,case when latest=1 then c=null else c end as difference
from
(
select id,Unique_Value,d,value,c,IF(#comp<>Unique_Value,1,0) as LATEST,#comp:=Unique_Value as company from
(
select t1.Id,t1.Unique_Value,value,t2.d,value-#quot as c,#quot:=value
from t1 inner join t2 on t1.id=t2.id
order by t1.Unique_Value,t2.d
)A order by Unique_Value,d
)B
OUTPUT:
id d value Unique_Value Difference
T-1 2018-01-01 10 OI-45
T-4 2018-03-15 15 OI-45 5
T-8 2018-05-12 25 OI-45 10
T-7 2018-04-01 12 OI-46
T-6 2018-06-01 18 OI-49

mysql select 2 table based on date and combine each other

i Need some help.. i have some case like this below
i have 2 table.. call ("in_table" and "out_table")
data "in_table" look like
stock_id item_id date qty_in
-----------------------------------------
1 11 2017-07-11 12
2 11 2017-07-11 10
3 12 2017-07-11 10
4 12 2017-07-19 10
And i have "out_table" is like
id_tr item_id date qty_out
-------------------------------------
1 11 2017-07-19 2
1 12 2017-07-19 1
2 11 2017-07-19 2
2 12 2017-07-19 1
And i want to combine the date and display all the data like this,
Update: the join is by item_id but i want to select by date
date item_id qty_in qty_out
---------------------------------------
2013-07-11 11 22 0
2013-07-11 12 10 0
2013-07-19 11 0 4
2013-07-19 12 10 2
Thank you for your help.
It looks like you need kind of a full outer join of two aggregate subqueries. But in your case I would get item_id and date in a union subquery (derived table) and the sums in correlated subqueries (subselect).
select item_id, date,
(select sum(qty_in) from in_table i where i.item_id = sub.item_id and i.date = sub.date) as qty_in,
(select sum(qty_out) from out_table o where o.item_id = sub.item_id and o.date = sub.date) as qty_out
from (
select item_id, date from in_table
union
select item_id, date from out_table
) sub
order by date, item_id

Group by and Order by latest

I want to group by id and order by begintime(latest row).
data:
begintime id type created_at
2012-12-13 01:00:00 1 type1 2012-12-01 11:39:47
2012-12-13 00:00:00 1 type2 2012-12-02 00:29:10
2012-12-13 03:00:00 2 type3 2012-12-05 00:20:43
2012-12-13 02:00:00 2 type2 2012-12-06 11:31:41
2012-12-13 00:00:00 2 type1 2012-12-07 00:58:11
I want to get:
begintime id type created_at
2012-12-13 01:00:00 1 type1 2012-12-01 11:39:47
2012-12-13 03:00:00 2 type3 2012-12-05 00:20:43
How can I get it?
Your title contradicts from the question you have written. It says LATEST but you really want the first created_AT for every ID. Anyway,
You could use a subquery which separately gets the minimum created_AT for every ID. The result of the subquery is then joined back to get the values of the other columns.
SELECT a.*
FROM TableName a
INNER JOIN
(
SELECT ID, MIN(created_AT) max_date
FROM TableName
GROUP BY ID
) b ON a.ID = b.ID AND
a.created_AT = b.max_date
SQLFiddle Demo
Try this:
SELECT *
FROM table_name
GROUP BY id
ORDER BY
id ASC,
begintime DESC;
Hope it helps!