I want to get not existed data from two tables - mysql

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')

Related

How to empty product name from duplicate rows

Can you help me with mysql query ? I would like to empty all duplicated product name and keep ONLY one row (product name and its SKU).
I wrote the query like this. Can you please confirm If it's the right syntax
UPDATE tvcom_product t1 JOIN
(SELECT name
FROM tvcom_product
GROUP BY name
HAVING count(product_id) > 1) dup ON t1.name = dup.name
SET t1.name = '' WHERE t1.sku != ''
UPDATE tvcom_product t1
JOIN tvcom_product t2 ON t2.name = t1.name AND t2.sku < t1.sku
SET t1.name = ''
This will reset name for all the records which have duplicates with same name. It will leave just one record with the smallest (alphabetically) SKU.
Instead of t2.sku < t1.sku you can write t2.id < t1.id - should be more optimal, it will leave out the record with smallest ID.
Upd. This is simplest but not most optimal way. For huge tables this one should work better:
UPDATE tvcom_product t1
JOIN (
SELECT name, MIN(id) id
FROM tvcom_product
GROUP BY name
HAVING COUNT(*) > 1
) t2 ON t1.name = t2.name AND t1.id != t2.id
SET t1.name = ''
If you want to optimise it even more then you should store the sub-query in a separate table and join it. Of course id in this query can be changed with sku.

How to get last modified row with condition

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

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
;

Joining three tables such that extra matches are discarded?

How can I write a query to give the results of three tables such that there's only one result per "line"?
The tables are:
T1 (ID, name, IP)
T2 (ID, date_joined)
T3 (ID, address, date_modified)
The relations are:
T1-T2 1:1, T1-T3 1:M - there can be many address rows per ID in T3.
What I want is a listing of all users with the fields above, but IF they have an address, I only want to record ONE (bonus would be if it is the latest one based on T3.date_modified).
So I should end up with exactly the number of records in T1 (happens to be equal to T2 in this case) and no more.
I tried:
select t.ID, t.name, t.IP, tt.ID, tt.date_joined, ttt.ID, ttt.address
from T1 t JOIN T2 tt ON (t.ID = tt.ID) JOIN T3 ttt ON (t.ID = ttt.ID)
And every sensible combination of LEFT, RIGHT, INNER, etc joins I could think of! I keep getting multiple duplicate because of T3
This query should work:
select
t1.ID, t1.name, t1.IP, t2.date_joined, t3x.address
from t1
join t2 on t1.ID = t2.id
left join (
select t3.*
from t3
join (
select id, max(date_modified) max_date
from t3
group by id
) max_t3 on t3.id = max_t3.id and t3.date_modified = max_t3.max_date
) t3x on t1.ID = t3x.id
First you do the normal join between t1 and t2 and then you left join with a derived table (t3x) that is the set of t3 rows having the latest date.
So T2 is actually not relevant here. You just need a way to join from T1 to T3 in a way that gets you at most one T3 row per T1 row.
One way of doing this would be:
select
T1.*,
(select address from T3 where T3.ID=T1.ID order by date_modified desc limit 1)
from T1;
This won't likely be very efficient, being a correlated subquery, but you may not care depending on the size of your dataset.
It's also only good for getting one column from T3, so if you had Address, City, and State, you'd have to figure out something else.
You can use sub query with Top 1 so that u get only one result from T3
here is a sample sql
select * into #T1 from(
select 1 ID
union select 2
union select 3) A
select * into #T2 from(
select 1 ID
union select 2
union select 3) A
select * into #T3 from(
select 1 ID, 'ABC' Address, getDate() dateModified
union select 1, 'DEF', getDate()
union select 3, 'GHI', getDate()) A
select *, (select top 1 Address from #T3 T3 where T3.ID= T1.ID order by datemodified desc) from #T1 T1
inner join #T2 T2 on T1.ID = T2.ID
Bonus :- you can also add order by dateModified desc to get the latest address

inner join for a query?

I want to do a sql query and have some problems:
I want to select from table_1 the ID's Where parent_id is the value I have:
SELECT ID
FROM table_1
WHERE parent_ID = 'x'
I want to use the ID'S I got in 1. and
SELECT
FROM table_2
WHERE ID = 'The ID's from Query 1.'
Like this?
select ...
from table_1 a
join table_2 b on(a.id = b.id)
where a.parent_id = 'x';
Edit
Note: the query will potentially produce duplicate rows depending on the keys and relation between the tables. For example, you will get duplicates if, for a given table_1.parent_id = X, there can be multiple occurrences of the same table_1.ID.
Another example is when table_2.ID isn't unique.
In those cases you would want to remove the duplicates (using distinct, group by, partitioned #row_number, etc) or, not produce the duplicates in the first place using a semi-join instead (exists, in). Have a look #OMG Ponies answer for reference.
Using IN
SELECT t2.*
FROM TABLE_2 t2
WHERE t2.id IN (SELECT t1.id
FROM TABLE_1 t1
WHERE t1.parent_id = 'x')
Using EXISTS
SELECT t2.*
FROM TABLE_2 t2
WHERE EXISTS (SELECT NULL
FROM TABLE_1 t1
WHERE t1.id = t2.id
AND t1.parent_id = 'x')
Using an INNER JOIN
The DISTINCT (or GROUP BY) is necessary to eliminate duplicates if there are more than one records in TABLE_1 that relate to a record in TABLE_2:
SELECT DISTINCT t2.*
FROM TABLE_2 t2
JOIN TABLE_1 t1 ON t1.id = t2.id
AND t1.parent_id = 'x'
It can be solved with the use of IN as follows:
SELECT * FROM table_2 WHERE ID IN (SELECT ID FROM table_1 WHERE parent_ID = 'x')
select * from table_2 where id in (select id from table_1 where parent_id = 'x')
Yes, it's better to you use this:
SELECT [value]
FROM [table2]
WHERE [value] IN (SELECT [value]
FROM [table1]
WHERE [value] = "[value]"
)