How to get last modified row with condition - mysql

I have below mentioned tables:
Table1:
ID Unique_Key Date MapId
II-10 RTE-011 2018-04-07 15:18:25 er-12-tt
II-11 RTE-011 2018-05-17 11:44:47 er-13-td
II-12 RTE-011 2018-06-12 13:22:29 ee-13-rt
II-13 RTE-012 2018-04-07 19:17:14 eg-15-st
II-14 RTE-012 2018-04-07 21:22:37 hr-15-yt
II-15 RTE-013 2018-07-07 20:27:38 tr-16-yt
II-15 RTE-013 2018-08-07 14:18:33 tr-16-yt
Table2:
Id Status
er-12-tt Open
er-13-td Closed
er-13-rt Closed
eg-15-st Closed
hr-15-yt Pending
tr-16-yt Open
tr-16-yt Pending
By using above mentioned both the tables, I want to fetch latest row of only those records which has status as Closed.
We need to exclude those Unique_Key against which any value is not equlal to Closed
Required Output would be:
ID Unique_Key Date MapId Id Status
II-12 RTE-011 2018-06-12 13:22:29 ee-13-rt er-13-rt Closed
II-13 RTE-012 2018-04-07 19:17:14 eg-15-st eg-15-st Closed

Firstly, in a subquery, we determine the maximum date for a group of Unique_Key. We filter out those Unique_Key values which has atleast one row with Status = Closed, using HAVING SUM(t2.Status = Closed) > 0
The result set of this sub-query is then utilized as a Derived Table. It is then joined back to Table1 and Table2, and we filter out those cases where maximum status is Closed, using WHERE t22.Status = 'Closed'
Try:
SELECT t11.ID,
t11.Unique_Key,
t11.Date,
t11.MapId,
t22.Id,
t22.Status
FROM Table1 AS t11
JOIN Table2 AS t22 ON t22.Id = t11.MapId
JOIN (
SELECT t1.Unique_Key,
MAX(t1.Date) AS max_Date
FROM Table1 AS t1
JOIN Table2 AS t2 ON t2.Id = t1.MapId
GROUP BY t1.Unique_Key
HAVING SUM(t2.Status = Closed) > 0
) AS dt ON dt.Unique_Key = t11.Unique_Key AND
dt.max_Date = t11.Date
WHERE t22.Status = 'Closed'

We can take a common approach here, and join to a subquery to do the filtering:
SELECT
t1.ID, t1.Unique_Key, t1.Date, t1.MapId, t2.Id, t2.Status
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.MapId = t2.Id
INNER JOIN
(
SELECT t1.Unique_Key, MAX(t1.Date) AS max_date
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.MapId = t2.Id
WHERE t2.Status = 'Closed'
GROUP BY t1.Unique_Key
) t3
ON t1.Unique_Key = t3.Unique_Key AND t1.Date = t3.max_date;
Demo
The join to the subquery aliased as t3 filters off all records for each unique key except for the most recent one which has a closed status.
For posterity's sake, there is another approach to this question using analytic functions. Given that MySQL 8+ will soon be the standard, it makes sense to consider this option as well:
SELECT
ID_t1, Unique_Key, Date, MapId, ID_t2, Status
FROM
(
SELECT t1.ID AS ID_t1, t1.Unique_Key, t1.Date, t1.MapId, t2.Id AS ID_t2,
t2.Status,
ROW_NUMBER() OVER (PARTITION BY t1.Unique_Key ORDER BY t1.Date DESC) rn
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.MapId = t2.Id
WHERE t2.Status = 'Closed'
) t
WHERE rn = 1;
Demo

Related

How to select the id with max value that in another table

Here are 2 tables.
Table 1
id value
1 3
2 2
3 3
4 1
5 4
6 3
Table 2
id
1
3
4
How do I get the ids that are in Table 2 which have the max value in Table 1?
Output:
id
1
3
I already tried the following to get the max value, but I cannot figure out how to use it in a single query to get the matching rows. Because I think I need to select from the same table I just inner joined.
select max(table1.value)
from table2
inner join table1 on table1.id = table2.id;
Here is one method:
select t2.id
from (select t2.*, rank() over (order by value desc) as seqnum
from table2 t2 join
table1 t1
on t2.id = t1.id
) t
where seqnum = 1;
Or, an alternative that puts all the ids on one row:
select group_concat(t2.id) as ids
from table2 t2 join
table1 t1
on t2.id = t1.id
group by t1.value
order by t1.value desc
limit 1;
You have a couple of options available without using window functions:
You can use a WHERE clause to select only id values that have a value equal to the MAX(value) from your query and an id that is in Table2:
SELECT t1.id
FROM Table1 t1
WHERE value = (
SELECT MAX(t1.value)
FROM Table2 t2
JOIN Table1 t1 ON t1.id = t2.id
)
AND id IN (SELECT id FROM Table2)
You can JOIN your query to Table1 and Table2 again, matching the value in Table1 and the id in Table2:
SELECT t1.id
FROM (
SELECT MAX(t1.value) AS max_value
FROM Table2 t2
JOIN Table1 t1 ON t1.id = t2.id
) t
JOIN Table1 t1 ON t1.value = t.max_value
JOIN Table2 t2 ON t2.id = t1.id
In both cases the output is
id
1
3
Demo on SQLFiddle
Too low to comment but from the SQL statement you gave, you just need to add the tableid in your select parameters.
select table2.id, max(table1.value)
from table2
inner join table1 on table1.id = table2.id;

I want to get not existed data from two tables

I have this MySQL query which links two tables.I want to join theme where to get not existed data from the other table.
this here get the registered date for users
SELECT
t2.name ,phone
FROM
(SELECT name,tid,date_d,class_time AS 'absent'
FROM absent where date_d = '2016-12-04' ) t1
JOIN
(SELECT name, id,phone AS 'phone'
FROM users ) t2
ON t1.tid = t2.id
group by id
I want the users who are not registered in table t1 from table two
I used the same above query but with something like this ON t1.tid != t2.idit works only with unduplicated date
SELECT
t2.name ,phone
FROM
(SELECT name,tid,date_d,class_time AS 'absent'
FROM absent where date_d = '2016-12-04' ) t1
JOIN
(SELECT name, id,phone AS 'phone'
FROM users ) t2
ON t1.tid != t2.id
group by id
A condition like ON t1.tid != t2.id used in a join will very likely give you a result if either t1 or t2 contain more than one row (because then, for some of the rows in t1 and t2, tid and id will be different). What you are looking for is "those users that have NOT been absent at a specific day, i.e. where no entry in absent-table exists", right?
Try the following:
SELECT name,id,phone AS 'phone'
FROM users t2
WHERE t2.id not in
(SELECT tid
FROM absent where date_d = '2016-12-04')

How to find latest row in a table corresponding to each row in a different table?

I thought I will get answer for this query straight away but I didn't find any Q&A which was exactly what I am looking for.
So, I have two tables.
Table 1: id,c_id,created_at
Table 2:id,c_id,b_date,s_type
I want a query which gives output corresponds to each row in table 1. The output should be the latest b_date in table 2 prior to created_at in Table 1 and the s_type corresponding to the latest b_date. The linking condition between Table 1 and Table 2 isc_id. Both the tables have multiple rows containing same c_id.
My table 1,table 2 and output will look like this.
I am not allowed to embed images as of now. So please click to see the images.
Possibly this
SELECT T1.ID,T1.C_ID,T1.CREATED_AT,T2.B_DATE,T2.S_TYPE
FROM TABLE1 T1
JOIN TABLE2 T2 ON T1.C_ID = T2.C_ID
WHERE T2.B_DATE = (SELECT MAX(T3.B_DATE) FROM TABLE2 T3 WHERE T3.b_DATE < T1.CREATED_AT AND T3.C_ID = T1.C_ID)
;
or maybe this
SELECT S.ID,S.C_ID,S.CREATED_AT,S.B_DATE,T.S_TYPE
FROM
(
SELECT T1.ID,T1.C_ID,T1.CREATED_AT,T2.B_DATE,T2.S_TYPE
FROM TABLE1 T1
JOIN TABLE2 T2 ON T1.C_ID = T2.C_ID
WHERE T2.B_DATE = (SELECT MAX(T3.B_DATE) FROM TABLE2 T3 WHERE T3.b_DATE < T1.CREATED_AT AND T3.C_ID = T1.C_ID)
) S
JOIN
(SELECT T1.ID,T1.C_ID,T1.CREATED_AT,T2.B_DATE,T2.S_TYPE
FROM TABLE1 T1
JOIN TABLE2 T2 ON T1.C_ID = T2.C_ID
WHERE T2.B_DATE = (SELECT MAX(T3.B_DATE) FROM TABLE2 T3 WHERE T3.C_ID = T1.C_ID)
) T ON S.C_ID = T.C_ID
;

How to count and get result of two rows in Mysql Select Query?

This is my table structure.
sometime table1 data my repeat (Ex : Actually Id 1 should have only 4 rows but sometime it is 8 due to duplication) so avoid duplication I use GROUP BY command in select query
Table 1
|id| website|time|
-----------------
|01|facebook|20.0|
|01|google |40.0|
|01|youtube |10.0|
|01|ebay |30.0|
|02|facebook|50.0|
|02|ebay |50.0|
Table 2
|id|marks|
-----------
|01| 80|
|02| 90|
|03| 70|
|04| 100|
I want to select (marks),(time on facebook) and (count of time on google & youtube) of specific user
Following select query gives (marks),(time on facebook) of user id '01'
How to receive count of time of both google and youtube of id'1' in same query ?
SELECT table2.id,table2.marks, table1.time
FROM table1
RIGHT JOIN table2 ON table1.id= table2.id
WHERE table1.website LIKE ('%facebook%')
AND table1.id= '01'
GROUP BY table1.id, table1.website
You want to find the time on facebook and then the sum of youtube and google for a particular user you can use the mysql conditional sum to achieve it
select
sum(case when t1.website = 'facebook' then t1.time else 0 end) as `fb_time`,
(
sum(case when t1.website='google' then t1.time else 0 end)+
sum(case when t1.website='youtube' then t1.time else 0 end)
)
as `google_youtube`,
t2.marks
from table1 t1
join table2 t2 on t1.id = t2.id
where t1.id = '01'
If you need to calculate the same for all the users then you can do it as
select
t1.id,
sum(case when t1.website = 'facebook' then t1.time else 0 end) as `fb_time`,
(
sum(case when t1.website='google' then t1.time else 0 end)+
sum(case when t1.website='youtube' then t1.time else 0 end)
)
as `google_youtube`,
t2.marks
from table1 t1
join table2 t2 on t1.id = t2.id
group by t1.id
If I understand your query correctly, I think you will need to use a subquery.
The following subquery returns two counts; time_on_facebook & time_on_google_and_youtube
for all users
SELECT t1.id, t2.marks,
COUNT(t1.time) as time_on_facebook,
(SELECT COUNT(t1_sq.time)
FROM `table1` as t1_sq
WHERE (t1_sq.website = "youtube" OR t1_sq.website = "google")
AND t1_sq.id = t1.id
GROUP BY t1.id) as time_on_google_and_youtube
FROM `table1` as t1
LEFT JOIN table2 t2 ON t2.id = t1.id
WHERE t1.website = "facebook"
GROUP BY t1.id
To restrict it to user id = 01, add in a WHERE clause
SELECT t1.id, t2.marks,
COUNT(t1.time) as time_on_facebook,
(SELECT COUNT(t1_sq.time)
FROM `table1` as t1_sq
WHERE (t1_sq.website = "youtube" OR t1_sq.website = "google")
AND t1_sq.id = t1.id
GROUP BY t1.id) as time_on_google_and_youtube
FROM `table1` as t1
LEFT JOIN table2 t2 ON t2.id = t1.id
WHERE t1.website = "facebook" AND t1.id = 1
GROUP BY t1.id
Are you sure you want COUNT(time) or do you want SUM(time)?
Lastly, consider adding a primary key to both tables and maybe rename the "id" column to "user_id" for clarity.
Its not clear what you want the output to look like. I made a query,
but did not try it. Try it and let me know if it works.
select t1.id, t1.website, sum(t1.time) as total_time, max(t2.marks) as marks
from table1 as t1
left join table2 as t2
on t1.id = t2.id
where t1.website = 'facebook'
and t1.id = '01'
group by t1.id, t1.website
UNION
select t1.id, t1.website, sum(t1.time) as total_time, max(t2.marks) as marks
from table1 as t1
left join table2 as t2
on t1.id = t2.id
where t1.website IN ('youtube', 'google')
and t1.id= '01'
group by t1.id, t1.website

How to retrieve the not common values from 2 tables?

I have the 2 following tables t1, t2 with values,
t1 t2
1 4
2 2
3 3
Now I want to output
1
4
How can I get this output in select query ?
This will get you each item from t1 that is not present in t2, and each item in t2 that is not present in t1:
select t1.id from t1
left join t2 on t2.id = t1.id
where t2.id is null
union all
select t2.id from t2
left join t1 on t1.id = t2.id
where t1.id is null
(I have assumed that the field name in each table is named id just for the sake of being able to write a query against the tables.)
Another way would be:
select coalesce(t1.id, t2.id)
from t1
full outer join t2 on t2.id = t1.id
where t1.id is null or t2.id is null
Another way. Just COUNT them.
This works if the values are unique per table
SELECT
CombinedValue
FROM
(
SELECT t1 AS CombinedValue FROM t1
UNION ALL
SELECT t2 FROM t2
) foo
GROUP BY
CombinedValue
HAVING
COUNT(*) = 1
If not unique per table
SELECT
CombinedValue
FROM
(
SELECT DISTINCT t1 AS CombinedValue FROM t1
UNION ALL
SELECT DISTINCT t2 FROM t2
) foo
GROUP BY
CombinedValue
HAVING
COUNT(*) = 1
you can use Joins in MySql to proceed and to obtain result.
this will help you
http://www.techrepublic.com/article/sql-basics-query-multiple-tables/1050307