I am trying to compose a SELECT statement for MySQL which select from table A what does not exist in table B. For example:
Table A:
+------+
| BAND |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
Table B:
+------+
| HATE |
+------+
| 1 |
| 5 |
+------+
So if table A is all bands, and table B is the bands I hate, then I only want bands I do NOT hate. So the result of a select should be:
+------+
| BAND |
+------+
| 2 |
| 3 |
| 4 |
+------+
How would I write a single select for this? Here was my last attempt:
SELECT * FROM A LEFT JOIN B ON A.BAND = B.HATE WHERE B.HATE IS NULL;
EDIT: The line above has been fixed! See comments below..."= NULL" versus "IS NULL".
I would use a join
select A.*
from A left join B on A.BAND = B.HATE
where B.HATE IS NULL;
Remember: Create the appropriate indexes for your table
You can use IN, but it's super inefficient:
SELECT * FROM tableA WHERE id NOT IN (SELECT id FROM tableB)
SELECT * FROM tableA WHERE id NOT EXISTS (SELECT DISTINCT id FROM tableB)
or
SELECT * FROM tableA WHERE id NOT EXISTS (SELECT id FROM tableB GROUP BY id)
SELECT BAND FROM A WHERE BAND NOT EXISTS(SELECT DISTINCT HATE FROM B)
OR
SELECT BAND FROM A WHERE NOT EXISTS ( SELECT HATE FROM B WHERE A.BAND = B.HATE);
Related
New to SQL
Suppose we have two tables
One has got the ID and Name column :
+----+-------+
| ID | Name |
+----+-------+
| 1 | Sam |
| 1 | Dan |
+----+-------+
and the second one has also got two columns as follow :
+----+------------+
| ID | Relatives |
+----+------------+
| 1 | Uncle |
| 2 | Aunty |
+----+------------+
If we do inner join we would only get the rows where the condition satisfies. But i want the output to be Like
+------+------------+
| ID | Relatives |
+------+------------+
| 1 | Uncle |
| NULL | Aunty |
+------+------------+
once only the value in the ID column should be shown. If the occurrence is twice or thrice it should come as null.
Just tell me if it is possible or not? and How for both the cases.
As your question is not clear, so assuming that you need to retrieve id from table a and name from table b and you also want to avoid duplicate rows, then an option could be to use distinct along with left join:
select distinct a.id, b.name
from b
left outer join a
on b.id = a.id
order by id desc
Result:
+------+-------+
| id | name |
+------+-------+
| 1 | Uncle |
| NULL | Aunty |
+------+-------+
DEMO
Try this:
SELECT
T1.Id,
T2.Relatives
FROM SecondTable T2
LEFT JOIN FirstTable T1
ON T1.ID = T2.ID
GROUP BY T1.Id,
T2.Relatives
This is what I get exactly:
CREATE TABLE #a (
id int,
name varchar(10)
)
CREATE TABLE #b (
id int,
name varchar(10)
)
INSERT INTO #a
VALUES (1, 'sam')
INSERT INTO #a
VALUES (1, 'Dan')
INSERT INTO #b
VALUES (1, 'Uncle')
INSERT INTO #b
VALUES (2, 'Aunty')
SELECT
T1.Id,
T2.name
FROM #b T2
LEFT JOIN #a T1
ON T1.ID = T2.ID
GROUP BY T1.Id,
T2.name
DROP TABLE #a
DROP TABLE #b
Output:
Id name
NULL Aunty
1 Uncle
Hope, this is what you ask in your question.
I am trying to get different values on rows of one table, and I can't think of how to that.
Lets say for example:
table1
id | name | empCode | insCode
1 John | E101 | I101
table2
id | code | name | role
1 | E101 | Mich | 2
2 | I101 | Bran | 3
table1 has reference id of table2, and empCode and insCode in table1 dependes on code and role in table2.
What I want is like this:
id | code | name | empCode | insCode | role |
1 | ? | John | E101 | I101 | ? |
I honestly don't know if its possible to retrieve multiple rows in same table in one select query.
If its not, what other possible solutions can I go with?
There is problem in your table design but you can get as your expected with below query:
select
result1.id,
result1.code,
result1.name,
result1.empCode,
result1.insCode,
result1.role as role_of_empCode,
result2.role as role_of_insCode
from (
SELECT tbl1.id,
tbl2.code,
tbl1.name,
tbl1.empCode,
tbl1.insCode,
tbl2.role
FROM `table2` tbl2
INNER JOIN `table1` tbl1
on tbl2.code = tbl1.empCode
) as result1,
`table2` result2
where result1.insCode = result2.code
ORDER BY result1.id;
You can check in this link!
Try something like:
SELECT a.*, b.role FROM
table1 a inner join table2 b on a.id=b.id
Also you may want to consider removing empcode and inscode from table 2 since its being redundant in table 1 OR vice versa depending on what your objectives are.
I am creating the following two temporary tables t1 and t2 using two SELECT statements:
+------+------+
| Col1 | Col2 |
+------+------+
| A | 1 |
| B | 2 |
| C | 3 |
+------+------+
and
+------+------+
| Col3 | Col4 |
+------+------+
| C | 5 |
| D | 6 |
| E | 7 |
+------+------+
The two SELECT statements by nature are always returning the same number of rows. Now I want to join/combine these two results horizontally to get the following output table:
+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 |
+------+------+------+------+
| A | 1 | C | 5 |
| B | 2 | D | 6 |
| C | 3 | E | 7 |
+------+------+------+------+
I tried working with multiple JOIN statement, but could figure out a smart way. I also tried the UNION statement, which delivered a vertical join, but not the required horizontal version.
Here two easy SELECT statement for better orientation in possible solutions:
SELECT * FROM `t1` WHERE date = DATE(NOW())
SELECT * FROM `t2` WHERE date = DATE(NOW())
Thanks in advance for your help.
Try this
SET #row_number_t1:=0;
SET #row_number_t2:=0;
SELECT t1_modif.*, t2_modif.* FROM
(SELECT #row_number_t1:=#row_number_t1+1 AS row_number,
t1.* FROM t1)
t1_modif
JOIN (SELECT #row_number_t2:=#row_number_t2+1 AS row_number,
t2.* FROM t2)
t2_modif ON t2_modif.row_number = t1_modif.row_number
Note that order is not guaranteed, to do this add ORDER BY clause at the end of each FROM t1 and FROM t2 subqueries, basically we are joining by row_number, since MySQL doesn't have ROW_ID, ROW_NUM (similar to mssql, oracle, postgres) we have used session variables
Creating Virtual IDs for relation. This is not a recommended way though.
SELECT col1, col2, col3, col4 FROM
(SELECT t1.*, (#t1VID := #t1VID + 1) t1VID FROM t1 , (SELECT #t1VID := 0) d) e
JOIN (SELECT t2.*, (#t2VID := #t2VID + 1) t2VID FROM t2, (SELECT #t2VID := 0) a ) b ON t1VID = t2VID
JOIN (SELECT #t1VID := 0) c ;
Ideal solution would have been adding proper relation between the tables. If not, it is best to query it separately and do the necessary joining in application layer
How do I go about creating a table from multiple tables having variable columns (union cannot be used)?
mysql> select * from a;
+------+------+
| id | name |
+------+------+
| 1 | Ruby |
+------+------+
mysql> select * from b;
+------+------+
| pid | name |
+------+------+
| 1 | Java |
| 1 | C++ |
+------+------+
What I want...
+------+------+------+------+
| id | name | pid | bname|
+------+------+------+------+
| 1 | Ruby | | |
| | | 1 | C++ |
| | | 1 | Java |
+------+------+------+------+
What I have tried.
mysql> create table t as select * from a; # worked fine
mysql> alter table t as select pid, name as bname from b; #didn't work
You can do this in this rather arcane way:
select a.*, b.*
from a left join
b
on 1 = 0
union all
select a.*, b.*
from b left join
a
on 1 = 0;
This is one way, in MySQL of implementing:
select a.*, b.*
from a full outer join
b
on 1 = 0;
But, it requires a union. You could do it in two steps if you want to avoid the union:
create table ab as
select a.*, b.*
from a left join
b
on 1 = 0;
insert into ab
select a.*, b.*
from b left join
a
on 1 = 0;
There's no problem to use union, you just need to select nulls as the columns that aren't in the table:
CREATE TABLE t AS
SELECT id, name, null AS pid, null AS bname
FROM a
UNION ALL
SELECT null, null, pid, bname
FROM b
Create the new table, containing all four columns. Then
INSERT INTO t (id, name) SELECT * FROM a;
INSERT INTO t (pid, bname) SELECT * FROM b;
The first line will put everything from a in there, and leave the other two fields as NULL; the second will do the corresponding thing from b. You could do the whole thing in one CREATE/UNION statement, but if this is a one-off operation, it's probably easier to understand what you're doing if you do it in stages like this.
You can try this this as an example.
Create a new table (name, date of birth) by joining two tables (student id, name) and (student id, date of birth).
Create first table:
create table stu1(student_id char(5) primary key,name varchar(45))ENGINE=innodb;
Create second table:
create table stu2(student_id char(5) primary key,dob date)ENGINE=innodb;
Create third table (by joining two tables):
create table stu3 AS(select stu1.name,stu2.dob from stu1,stu2
where stu1.student_id=stu2.student_id);
I am trying to get some rows from the same table. It's a user table: user has user_id and user_parent_id.
I need to get the user_id row and user_parent_id row. I have coded something like this:
SELECT user.user_fname, user.user_lname
FROM users as user
INNER JOIN users AS parent
ON parent.user_parent_id = user.user_id
WHERE user.user_id = $_GET[id]
But it doesn't show the results. I want to display user record and its parent record.
I think the problem is in your JOIN condition.
SELECT user.user_fname,
user.user_lname,
parent.user_fname,
parent.user_lname
FROM users AS user
JOIN users AS parent
ON parent.user_id = user.user_parent_id
WHERE user.user_id = $_GET[id]
Edit:
You should probably use LEFT JOIN if there are users with no parents.
You can also use UNION like
SELECT user_fname ,
user_lname
FROM users
WHERE user_id = $_GET[id]
UNION
SELECT user_fname ,
user_lname
FROM users
WHERE user_parent_id = $_GET[id]
Perhaps this should be the select (if I understand the question correctly)
select user.user_fname, user.user_lname, parent.user_fname, parent.user_lname
... As before
Your query should work fine, but you have to use the alias parent to show the values of the parent table like this:
select
CONCAT(user.user_fname, ' ', user.user_lname) AS 'User Name',
CONCAT(parent.user_fname, ' ', parent.user_lname) AS 'Parent Name'
from users as user
inner join users as parent on parent.user_parent_id = user.user_id
where user.user_id = $_GET[id];
I don't know how the table is created but try this...
SELECT users1.user_id, users2.user_parent_id
FROM users AS users1
INNER JOIN users AS users2
ON users1.id = users2.id
WHERE users1.user_id = users2.user_parent_id
Lets try to answer this question, with a good and simple scenario, with 3 MySQL tables i.e. datetable, colortable and jointable.
first see values of table datetable with primary key assigned to column dateid:
mysql> select * from datetable;
+--------+------------+
| dateid | datevalue |
+--------+------------+
| 101 | 2015-01-01 |
| 102 | 2015-05-01 |
| 103 | 2016-01-01 |
+--------+------------+
3 rows in set (0.00 sec)
now move to our second table values colortable with primary key assigned to column colorid:
mysql> select * from colortable;
+---------+------------+
| colorid | colorvalue |
+---------+------------+
| 11 | blue |
| 12 | yellow |
+---------+------------+
2 rows in set (0.00 sec)
and our final third table jointable have no primary keys and values are:
mysql> select * from jointable;
+--------+---------+
| dateid | colorid |
+--------+---------+
| 101 | 11 |
| 102 | 12 |
| 101 | 12 |
+--------+---------+
3 rows in set (0.00 sec)
Now our condition is to find the dateid's, which have both color values blue and yellow.
So, our query is:
mysql> SELECT t1.dateid FROM jointable AS t1 INNER JOIN jointable t2
-> ON t1.dateid = t2.dateid
-> WHERE
-> (t1.colorid IN (SELECT colorid FROM colortable WHERE colorvalue = 'blue'))
-> AND
-> (t2.colorid IN (SELECT colorid FROM colortable WHERE colorvalue = 'yellow'));
+--------+
| dateid |
+--------+
| 101 |
+--------+
1 row in set (0.00 sec)
Hope, this would help many one.