Compare two database table - mysql

I have two database tables, tmp1 and tmp2
tmp1:
+----+------+---------+---------+
| id | name | add1 | add2 |
+----+------+---------+---------+
| 1 | NULL | NULL | NULL |
| 2 | NULL | NULL | NULL |
| 3 | mum1 | rajpur1 | rajpur2 |
| 4 | mum3 | rajpur3 | rajpur4 |
| 5 | mum4 | rajpur4 | rajpur5 |
+----+------+---------+---------+
tmp2:
+----+------+---------+---------+
| id | name | add1 | add2 |
+----+------+---------+---------+
| 1 | NULL | NULL | NULL |
| 2 | mum | rajpur | rajpur1 |
| 3 | NULL | NULL | NULL |
| 4 | mum2 | rajpur2 | rajpur3 |
| 5 | mum4 | rajpur4 | rajpur5 |
+----+------+---------+---------+
select a.id
from tmp1 a
inner join tmp2 b
where a.id = b.id
and (a.name is NULL or a.add1 is NULL or a.add2 is NULL)
or (a.name!=b.name or a.add1!=b.add1 or a.add2!=b.add2);
Here I have tried the above code to show the following result:
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
+----+
But it doesn't show me the desired result.
Here i want to print the first table's id where one or many other row's values are either null or one or many other row's values are unmatched with tmp2's those rows values.

You were missing the ON. And as The Impaler astutely pointed out, the columns in the temp2 also need to be checked for NULL.
select a.id
from tmp1 a
inner join tmp2 b on a.id=b.id
where coalesce(a.name,a.add1,a.add2,b.name,b.add1,b.add2) is null or
coalesce(a.name,a.add1,a.add2)<>coalesce(b.name,b.add1,b.add2));

You are missing the ON clause that specifies how to join the table(s). Also, your search condition is incomplete.
select a.id
from tmp1 a
join tmp1 b on a.id = b.id
where a.name is null or a.add1 is null or a.add2 is null
or b.name is null or b.add1 is null or b.add2 is null
or (a.name <> b.name or a.add1 <> b.add1 or a.add2 <> b.add2)

Related

Joining INTO many-to-many table (From Primary Key Table)

This is how far i have gotten, though i don't think it can be done with 1 SQL-statement, i just want to confirm whether or not it is possible to do this with ONLY 1 statement:
SELECT * FROM users
INNER JOIN users_mentors ON users_mentors.id=users.mentoruser_id
INNER JOIN mentor_types ON (mentor_types.id=users_mentors.mentor_type OR users_mentors.mentor_type IS NULL)
INNER JOIN mentor_geographies ON mentor_geographies.mentor_id=users_mentors.id
INNER JOIN communes ON communes.id=mentor_geographies.commune_id
LIMIT 0,10
users table with foreignkey to users_mentors:
+------+---------+---------------+
| id | user_id | mentoruser_id |
+------+---------+---------------+
| 1886 | NULL | 4 |
| 1885 | NULL | NULL |
| 1884 | NULL | NULL |
| 1883 | NULL | NULL |
| 1882 | NULL | NULL |
+------+---------+---------------+
users_mentors table (in a many-to-many relationship with communes):
+----+-------------+
| id | mentor_type |
+----+-------------+
| 4 | NULL |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+-------------+
communes table (in a many-to-many relationship with users_mentors):
+----+--------------+-------+----------+
| id | name | short | contract |
+----+--------------+-------+----------+
| 1 | København | NULL | 0 |
| 2 | Aarhus | NULL | 0 |
| 3 | Aalborg | NULL | 0 |
| 4 | Odense | NULL | 0 |
| 5 | Esbjerg | NULL | 0 |
+----+--------------+-------+----------+
mentor_geographies table (the m2m table that has FK to communes & users_mentors):
+----+-----------+------------+
| id | mentor_id | commune_id |
+----+-----------+------------+
| 1 | 4 | 1 |
| 2 | 4 | 2 |
+----+-----------+------------+
Is it possible to get all rows from users_mentors and a list of all their commune.type's, IF THEY EXIST (if mentor_geographies is empty, i want empty list of commune.type). In all cases i want the user.
If you want all users, use left join:
SELECT *
FROM users LEFT JOIN
users_mentors
ON users_mentors.id = users.mentoruser_id LEFT JOIN
mentor_types
ON mentor_types.id=users_mentors.mentor_type OR
users_mentors.mentor_type IS NULL LEFT JOIN
mentor_geographies
ON mentor_geographies.mentor_id = users_mentors.id LEFT JOIN
communes
ON communes.id = mentor_geographies.commune_id
LIMIT 0, 10;
I would also recommend that you use table aliases. They make the queries easier to write and to read:
SELECT *
FROM users u LEFT JOIN
users_mentors um
ON um.id = u.mentoruser_id LEFT JOIN
mentor_types mt
ON mt.id = um.mentor_type OR
um.mentor_type IS NULL LEFT JOIN
mentor_geographies mg
ON mg.mentor_id = um.id LEFT JOIN
communes c
ON c.id = mg.commune_id
LIMIT 0, 10

How to join get data from 2 tables and left join into 1 table in mysql

I have this table
tbl_emp
ID| name |
1 | a |
2 | b |
3 | c |
4 | d |
tbl_remit
ID| remit |
1 | 2012-01-01|
2 | 2013-01-01|
3 | 2012-05-01|
tbl_report
ID| report |
1 | 2012-01-01|
2 | 2013-01-01|
3 | 2012-05-01|
I need to join all 3 of them in tbl_emp regardless if there is a data in tbl_remit or tbl_report.
Here is the code that I used but failed.
SELECT tbl_emp*, tbl_remit.remit, tbl_report.report from tbl_emp
left join tbl_emp.ID = tbl_remit.ID LEFT JOIN tbl_emp.ID = tbl_report.ID
the table i got was
ID | remit | report |
1 | NULL | NULL |
2 | NULL | NULL |
3 | NULL | NULL |
4 | NULL | NULL |
the table i need is
ID | remit | report |
1 |2012-01-01|2012-01-01|
2 |2013-01-01|2013-01-01|
3 |2012-05-01|2012-05-01|
4 | NULL | NULL |
You can do this by joining your other two tables with inner join. And the join the resulted table with the emp table. For that you can use subquery.
select * from tbl_emp x left join (
select a.id as id, a.remit as remit,b.report as report from
tbl_remita,tbl_report b where a.id=b.id) y on x.id = y.id
Hope it will help.

MySQL - IF within SELECT

I have the following MySQL query:
SELECT id, name, parent_id AS pID,
(SELECT parent_id
FROM category
WHERE id = pID)
AS grandparent_id,
(SELECT parent_id
FROM category
WHERE id = grandparent_id)
AS greatgrandparent_id,
(SELECT name
FROM category
WHERE id = pID)
AS parent,
(SELECT name
FROM category
WHERE id = grandparent_id)
AS grandparent,
(SELECT name
FROM category
WHERE id = greatgrandparent_id)
AS greatgrandparent
FROM category
WHERE active = '1'
HAVING grandparent IS NOT NULL
ORDER BY grandparent_id, parent_id, sort, id ASC
When the greatgrandparent IS NULL I want it to display the grandparent value instead. Is this possible?
I've tried CASE WHEN but must be getting the syntax wrong somewhere as it keeps throwing an error.
Simple solution: IFNULL(greatgrandparent, grandparent).
You cannot have a having clause without a group by clause.
May be this code helps you.
SELECT id, name, parent_id AS pID,
case when grandparent IS NOT NULL then
(SELECT parent_id FROM category WHERE id = grandparent_id)
else
(SELECT parent_id FROM category WHERE id = pID)
end as _parent_id,
case when grandparent IS NOT NULL then
(SELECT name FROM category WHERE id = grandparent_id)
else
(SELECT name FROM category WHERE id = pID)
end AS _parent_name
FROM category WHERE active = '1'
ORDER BY grandparent_id, parent_id, sort, id ASC
I would rewrite this using left joins with aliases and coalesce.
Given this
/*
CREATE TABLE CATEGORY(ID INT, NAME VARCHAR(20), PARENT_ID INT);
TRUNCATE TABLE CATEGORY;
INSERT INTO CATEGORY VALUES
(1,'AAAA',2),(2,'AAA',3),(3,'AA',4),(4,'A',5),
(10,'BBBB',11),(11,'BBB',12)
;
*/
This code
SELECT C.ID,C.NAME,C.PARENT_ID ,
CP.NAME AS PARENTNAME,CP.PARENT_ID AS PARENT_PARENT_ID,
CG.NAME AS GRANDPARENTNAME,
CG.PARENT_ID AS GRANDPARENT_PARENT_ID,
CGG.NAME AS GREATGRANDPARENTNAME ,
CGG.PARENT_ID AS GREATGRANDPARENT_PARENT_ID
FROM CATEGORY C
LEFT JOIN CATEGORY CP ON CP.ID = C.PARENT_ID
LEFT JOIN CATEGORY CG ON CG.ID = CP.PARENT_ID
LEFT JOIN CATEGORY CGG ON CGG.ID = CG.PARENT_ID
ORDER BY C.ID;
Results in
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
| ID | NAME | PARENT_ID | PARENTNAME | PARENT_PARENT_ID | GRANDPARENTNAME | GRANDPARENT_PARENT_ID | GREATGRANDPARENTNAME | GREATGRANDPARENT_PARENT_ID |
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
| 1 | AAAA | 2 | AAA | 3 | AA | 4 | A | 5 |
| 2 | AAA | 3 | AA | 4 | A | 5 | NULL | NULL |
| 3 | AA | 4 | A | 5 | NULL | NULL | NULL | NULL |
| 4 | A | 5 | NULL | NULL | NULL | NULL | NULL | NULL |
| 10 | BBBB | 11 | BBB | 12 | NULL | NULL | NULL | NULL |
| 11 | BBB | 12 | NULL | NULL | NULL | NULL | NULL | NULL |
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
and this code
SELECT C.ID,C.NAME,C.PARENT_ID ,
CP.NAME AS PARENTNAME,CP.PARENT_ID AS PARENT_PARENT_ID,
COALESCE(CG.NAME,CP.NAME) AS GRANDPARENTNAME,
COALESCE(CG.PARENT_ID,CP.PARENT_ID) AS GRANDPARENT_PARENT_ID,
COALESCE(CGG.NAME,CG.NAME) AS GREATGRANDPARENTNAME ,
COALESCE(CGG.PARENT_ID,CG.PARENT_ID) AS GREATGRANDPARENT_PARENT_ID
FROM CATEGORY C
LEFT JOIN CATEGORY CP ON CP.ID = C.PARENT_ID
LEFT JOIN CATEGORY CG ON CG.ID = CP.PARENT_ID
LEFT JOIN CATEGORY CGG ON CGG.ID = CG.PARENT_ID
ORDER BY C.ID
results in
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
| ID | NAME | PARENT_ID | PARENTNAME | PARENT_PARENT_ID | GRANDPARENTNAME | GRANDPARENT_PARENT_ID | GREATGRANDPARENTNAME | GREATGRANDPARENT_PARENT_ID |
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
| 1 | AAAA | 2 | AAA | 3 | AA | 4 | A | 5 |
| 2 | AAA | 3 | AA | 4 | A | 5 | A | 5 |
| 3 | AA | 4 | A | 5 | A | 5 | NULL | NULL |
| 4 | A | 5 | NULL | NULL | NULL | NULL | NULL | NULL |
| 10 | BBBB | 11 | BBB | 12 | BBB | 12 | NULL | NULL |
| 11 | BBB | 12 | NULL | NULL | NULL | NULL | NULL | NULL |
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+

Multiple inner join on a table where rows represent data attributes

I have the following user table (don't ask me why :) )
| id | cid | attr | text | rdate |
---------------------------------------
| 1 | 1 | name | joe | NULL |
| 2 | 1 | date | NULL | 10.05.2014 |
| 3 | 1 | stat | 2 | NULL |
----------------------------------------
| 4 | 2 | name | joe | NULL |
| 5 | 2 | date | NULL | 05.05.2014 |
| 6 | 2 | stat | 1 | NULL |
----------------------------------------
| 7 | 3 | name | joe | NULL |
| 8 | 3 | date | NULL | 03.05.2014 |
| 9 | 3 | stat | 2 | NULL |
As you can see every user's attribute (name, date, stat) is a row in the table.
Attributes with the same cid belong to the same user.
I would like to delete all the entries which refer to a user whose attribute date is before 08.05.2014 AND whose attribute stat is not 2. So after running this query the table will be:
| id | cid | attr | text | rdate |
---------------------------------------
| 1 | 1 | name | joe | NULL |
| 2 | 1 | date | NULL | 10.05.2014 |
| 3 | 1 | stat | 2 | NULL |
----------------------------------------
| 7 | 3 | name | joe | NULL |
| 8 | 3 | date | joe | 03.05.2014 |
| 9 | 3 | stat | 2 | NULL |
Is it possible? Is this a inner join on the same table?
Group by the cid and use the having clause to run group functions to check out your requirements in every single group
delete from your_table
where cid in
(
select * from
(
select cid
from your_table
group by cid
having sum(attr = 'date' and `date` < '2014-05-08') > 0
and sum(attr = 'stat' and `text` = 2) = 0
) tmp_tbl
)
In MySQL you can't delete from the same table you are selecting from. But you can trick MySQL with another subquery like in the example above.
You can do this with delete/join:
delete t
from table t join
(select cid
from table t
group by cid
having max(case when attr = 'date' and date < '2014-05-08') > 0 and
max(case when attr = 'stat' and text <> '2') > 0
) s
on t.cid = s.cid;
I would do a fairly simple JOIN in the delete statement:-
DELETE a
FROM some_table a
INNER JOIN some_table b
ON a.cid = b.cid
INNER JOIN some_table c
ON a.cid = c.cid
WHERE b.attr = 'date' AND b.date < '2014-05-08'
AND c.attr = 'stat' AND c.text != '2'
Join will do :
Delete from mytable where cid in (select cid from
(select t1.cid FROM mytable t1 INNER JOIN mytable t2 ON t1.cid = t2.cid
WHERE t1.attr = 'date' AND t1.rdate < '2014-05-08'
AND t2.attr = 'stat' AND t2.text != 2) as sq)

How to pair date rows in mysql

How to pair rows with imperfecty in mysql? Imperfect, meaning the rows are not exactly paired as in and out. Sometimes, there are two in with one out or no out at all or two or more out with one in or no in at all.
The table look like this:
| id | action | date |
+----+--------+---------------------+
| 1 | in | 19.1.2012 15:41:52 |
| 1 | out | 19.1.2012 15:55:52 |
| 2 | in | 19.2.2012 15:55:52 |
| 2 | out | 19.2.2012 17:55:53 |
| 1 | in | 19.3.2012 15:55:54 |
| 1 | in | 19.3.2012 17:55:55 |
| 1 | out | 19.3.2012 19:55:56 |
| 3 | in | 19.4.2012 15:55:57 |
| 3 | out | 19.4.2012 17:55:58 |
| 3 | out | 19.4.2012 19:55:59 |
+----+--------+---------------------+
The desired result is like this:
+----+--------+---------------------+
| id | action | date |
+----+--------+---------------------+
| 1 | in | 19.1.2012 15:41:52 |
| 1 | out | 19.1.2012 15:55:52 |
| 2 | in | 19.2.2012 15:55:52 |
| 2 | out | 19.2.2012 17:55:53 |
| 1 | in | 19.3.2012 17:55:55 |
| 1 | out | 19.3.2012 19:55:56 |
| 3 | in | 19.4.2012 15:55:57 |
| 3 | out | 19.4.2012 17:55:58 |
+----+--------+---------------------+
This is the best desireed result
+----+---------------------+---------------------+
| id | date_in | date_out |
+----+---------------------+---------------------+
| 1 | 19.1.2012 15:41:52 | 19.1.2012 15:55:52 |
| 2 | 19.2.2012 15:55:52 | 19.2.2012 17:55:53 |
| 1 | 19.3.2012 17:55:55 | 19.3.2012 19:55:56 |
| 3 | 19.4.2012 15:55:57 | 19.4.2012 17:55:58 |
+----+---------------------+---------------------+
Here is a code, but it yields different result, can anyone figure out where the error is?
enter code here SELECT c.e_id
, CAST(c.in_time AS DATETIME) AS in_time
, c.out_time
FROM (
SELECT IF(#prev_id = d.id,#in_time,#in_time:=NULL) AS reset_in_time
, #in_time := IF(d.action = 'in',d.date,#in_time) AS in_time
, IF(d.action = 'out',d.date,NULL) AS out_time
, #prev_id := d.id AS id
FROM (
SELECT id, date_, action
FROM e
JOIN (SELECT #prev_id := NULL, #in_time := NULL) f
ORDER BY id, date, action
) d
) c
WHERE c.out_time IS NOT NULL
ORDER BY c.out_time enter code here
This selects an in event into a, an out event into b and uses a LEFT JOIN to eliminate the row if there exists an event c for the same id between them; that will simply get all in/out times that don't have an extra in or out between them.
SELECT a.id, a.date date_in, b.date date_out
FROM mytable a
JOIN mytable b
ON a.id = b.id AND a.date < b.date
LEFT JOIN mytable c
ON a.id = c.id AND c.date < b.date AND c.date > a.date
WHERE a.action = 'in' AND b.action = 'out' AND c.action IS NULL
ORDER BY a.date;
An SQLfiddle to test with.