This is my table :
What I'm trying to do, is to take the last disponibility of a user, by caserne. Example, I should have this result :
id id_user id_caserne id_dispo created_at
31 21 12 1 2019-10-24 01:21:46
33 21 13 1 2019-10-23 20:17:21
I've tried this sql, but it does not seems to work all the times :
SELECT * FROM
( SELECT id, id_dispo, id_user, id_caserne, MAX(created_at)
FROM disponibilites GROUP BY id_user, id_caserne, id_dispo
ORDER BY created_at desc ) AS sub
GROUP BY id_user, id_caserne
What am I doing wrong ?
I would simply use filtering in the where clause using a correlated subquery:
select d.*
from disponibilites d
where d.created_at = (select max(d2.created_at)
from disponibilites d2
where d2.id_user = d.id_user
);
EDIT:
Based on your comments:
select d.*
from disponibilites d
where d.created_at = (select max(d2.created_at)
from disponibilites d2
where d2.id_user = d.id_user and
d2.id_caserne = d.id_caserne
where date(d2.created_at) = date(d.created_at)
);
You can use a correlated subquery, as demonstrated by Gordon Linoff, or a window function if your RDBMS supports it:
select * from (
select
t.*,
rank() over(partition by id_caserne, id_user order by created_at desc) rn
from disponibilites t
) x
where rn = 1
Another option is to use a correlated subquery without aggregation, only with a sort and limit:
select *
from mytable t
where created_at = (
select created_at
from mytable t1
where t1.id_user = t.id_user and t1.id_caserne = t.id_caserne
order by created_at desc
limit 1
)
With an index on (id_user, id_caserne, created_at), this should be a very efficient option.
you can join your max(created_date) to your original table
select t1.* from disponibilites t1
inner join
(select max(created_at), id_caserne, id
from disponibilites
group by id_caserne, id) t2
on t2.id = t1.id
Related
table1 has 3 columns in my database: id, category, timestamp. I need to query the newest 3 rows from each category:
WITH ranked_rows AS
(SELECT t.*, ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS rn
FROM table1 AS t)
SELECT ranked_rows.* FROM ranked_rows WHERE rn<=3
now I need to select 10 partitions from the results randomly (please notice that each partition has 3 rows). how to do that?
There are various methods. One is:
WITH ranked_rows AS (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS seqnum,
DENSE_RANK() OVER (ORDER BY MD5(category)) as catnum
FROM table1 t
)
SELECT ranked_rows.*
FROM ranked_rows
WHERE seqnum <= 3 AND catnum <= 10;
The md5() just makes the results look random.
if you want true random per category, here is one way :
with categorycte as (
select category , rand() randomcatid
from table1
group by category
),ranked_rows AS
(
SELECT t.*
, ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS rn
, dense_rank() over (order by randomcatid) catnum
FROM table1 AS t
join categorycte c on t.category = c.category
)
SELECT ranked_rows.* FROM ranked_rows
WHERE rn<=3 and catnum <= 10;
i have a mysql table with colums: id(primary), name(varchar), TIME(timestamp)
ID , NAME , TIME
i want to get just first and last log for each day
example if i have data like this
1,name,2018-20-21 12:35:00
2,name,2018-20-21 13:38:00
3,name,2018-20-21 14:25:00
4,name,2018-20-21 15:39:00
5,name,2018-20-21 21:48:00
6,name,2018-20-22 13:25:00
7,name,2018-20-22 14:39:00
8,name,2018-20-22 19:48:00
i want to get in just this
1,name,2018-20-21 12:35:00
5,name,2018-20-21 21:48:00
6,name,2018-20-22 13:25:00
8,name,2018-20-22 19:48:00
Try this:
SELECT name, MAX(time), MIN(time) FROM Table GROUP BY DATE(time);
You could use the union for the min and the max time group by date
and join this with your table
select * from my_table
inner join (
select * from (
select min(time) my_time
from my_table
group by date(time)
union
select max(time)
from my_table
group by date(time)
) t on t.my_time = my_table.time
order by my_table.time
Hope this helps.
SELECT id, tmp.name, tmp.time FROM
(SELECT id, name, min(time) as time FROM table1 GROUP BY DATE(time)
UNION ALL
(SELECT id, name, max(time) as time FROM table1 GROUP BY DATE(time)) tmp
ORDER BY tmp.time
You can try selecting the min and max for each day, since you want the entire line, a join is needed
and to filter out the actual min and max day, a aub query is needed
SELECT id, name, time
FROM
(
SELECT t2.*, MIN(DATE(t.time)) As min0 MAX(DATE(t.time)) As max0
FROM
table t
INNER JOIN table t2 ON t.id = t2.id
GROUP BY
DATE (t.time),
min0,
max0
) a
SELECT
l.id,l.name,l.time
FROM
log l
LEFT JOIN
(SELECT
max(time) as maxTime
FROM
log
GROUP BY date(time)) l1 ON l.time = l1.maxTime
LEFT JOIN
(SELECT
min(time) as minTime
FROM
log
GROUP BY date(time)) l2 ON l.time = l2.minTime
WHERE
(maxTime IS NOT NULL
OR minTime IS NOT NUll);
SELECT * from stack.log;
Having this query,
SELECT DISTINCT ID, DATE FROM MAIN_TAB ORDER BY ID ASC
How can I print the total of different combinations for ID field, on the front of every row, example TOTAL_DISTINCT_VALUES:
ID DATE TOTAL_DISTINCT_VALUES
37870 02/07/2018 3
37870 03/07/2018 3
37870 04/07/2018 3
55887 04/07/2018 2
55887 03/07/2018 2
61891 02/07/2018 1
44891 02/07/2018 1
75891 02/07/2018 1
You could use count and group by
SELECT ID, DATE, count(*) TOTAL_DISINCT_VALUE
FROM MAIN_TAB
GROUP BY ID, DATE
ORDER BY ID ASC
but looking to you data sample seems you need cont only for id so you could use a join on the count group by id
select t.id, a.date, t.TOTAL_DISTINCT_VALUE
from MAIN_TAB a
inner JOIN (
select id, count(*) TOTAL_DISTINCT_VALUE
FROM MAIN_TAB
group by ID
) t on a.id = t.id
or as suggested by barmar . count(distinct date)
select t.id, a.date, t.TOTAL_DISTINCT_VALUE
from MAIN_TAB a
inner JOIN (
select id, count(distinct date) TOTAL_DISTINCT_VALUE
FROM MAIN_TAB
group by ID
) t on a.id = t.id
use group by clause
SELECT ID, DATE,count(*) as distinct_value FROM MAIN_TAB
group by ID, DATE
ORDER BY ID ASC
Try this:
select ID,DATE,count(*) as TOTAL_DISINCT_VALUE from MAIN_TAB group by ID,DATE order by ID asc;
and replace * with any other column name except ID and DATE.
I have 100 records from 3 users. I want to show the most recent record from each user. I have the following query:
SELECT *
FROM Mytable
WHERE Dateabc = CURRENT DATE
AND timeabc =
(
SELECT MAX(timeabc)
FROM Mytable
)
It returns the most recent record for everyone, and I need it to return most recent record from every user.
Should the solution support both DB2 and mysql?
SELECT * FROM Mytable as x
WHERE Dateabc = CURRENT_DATE
AND timeabc = (SELECT MAX( timeabc ) FROM Mytable as y where x.user = y.user)
If it's only DB2 more efficient solutions exists:
SELECT * from (
SELECT x.*, row_number() over (partition by user order by timeabc desc) as rn
FROM Mytable as x
)
WHERE rn = 1
I assume somewhere in your table you have a userID...
select userID, max(timeabc) from mytable group by userID
SELECT *
FROM Mytable as a
WHERE Dateabc = CURRENT_DATE
AND timeabc =
(
SELECT MAX( timeabc )
FROM Mytable as b
WHERE a.uId = b.uId
)
It's possible get a random value of the group by?
----------------
nID | val
---------------
A | XXX
A | YYY
B | L
B | M
B | N
B | P
----------------
With this SQL:
SELECT nID, VAL FROM T1 GROUP BY nID
My result always is:
nID val
--------
A XXX
B L
But i want a diferent result of evey nID. Like:
nID val
--------
A YYY
B N
or
nID val
--------
A XXX
B P
It's possible?
http://sqlfiddle.com/#!2/357b8/3
Use a sub-query.
SELECT r.nID,
(SELECT r1.val FROM T1 r1 WHERE r.nID=r1.nID ORDER BY rand() LIMIT 1) AS 'val' FROM T1 r
GROUP BY r.nID
http://sqlfiddle.com/#!2/357b8/18
You can use order by rand()
then group by them.
Like
SELECT nID, VAL FROM (
SELECT nID, VAL
FROM T1
ORDER BY RAND()
)AS subquery
GROUP BY nID
SELECT
t1.nID,
(SELECT
t2.var
FROM your_table t2
WHERE t1.nID = t2.nID ORDER BY rand() LIMIT 1
) AS var
FROM your_table t1
GROUP BY t1.nID ;
Try This
SELECT nID, VAL
FROM (select nID, VAL from T1 order by rand()) as T
group by nID
The following solution is similar in spirit to those from xdazz or jonnyynnoj. But instead of SELECT FROM T1 GROUP BY nID I use a subquery to select all distinct IDs. I believe there is a chance that the performance might differ, so give this one a try as well.
SELECT nID,
(SELECT VAL
FROM T1
WHERE T1.nID = ids.nID
ORDER BY RAND()
LIMIT 1
) AS VAL
FROM (SELECT DISTINCT nID FROM T1) AS ids
rand + rownum
SELECT t.*
, #rownum := #rownum+1 AS rowNum
FROM(
SELECT nID, VAL
FROM T1
ORDER BY RAND()
) AS t, (SELECT #rownum :=0) AS R
GROUP BY nID
ORDER BY nID, rowNum