How to create table as select from multiple tables? - mysql

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

Related

mysql insert and select between 3 tables

i am looking for a better way to handle the following problem.
custData
--------
ID | Code
1 | A
2 | B
prodData
--------
ID | ProdID
1 | prodA
2 | prodB
3 | prodC
and i would like to keep a record in this table:
custProdPrice
--------
ID | Cust | Prod
1 | A | prodA
2 | A | prodB
3 | A | prodC
4 | B | prodA
5 | B | prodB
6 | B | prodC
i was getting it done by using the following query
create view CashPOSDB.viewertable as select Code, ProdID as pid, BelongTo
from CashPOSDB.custData cross join CashPOSDB.prodData
AND
insert into CashPOSDB.custProdPrice(Cust, Prod, BelongTo)(select Code, Pid, BelongTo from
(select Code, pid, belongTo from CashPOSDB.viewertable UNION ALL
select Cust, Prod, BelongTo from CashPOSDB.custProdPrice) t group by Code, Pid);
It does the job, but it seems like its missing some result sometimes or inserting duplicate rows.
Also, I would like it to check so that when I insert a new Prod prodD, it would check in custProdPrice and see if cust A and B already has a row of
A | prodD
b | prodD
and insert it if it doesn't exist.
So what would the best way be to optimize this?
Give the custProdPrice table a unique index on (Cust, Prod) to prevent duplicates:
ALTER TABLE custProdPrice ADD UNIQUE INDEX (Cust, Prod);
Then use INSERT IGNORE to skip duplicates.
There doesn't seem to be any reason to UNION with custProdPrice when inserting into custProdPrice. Just insert the cross product.
INSERT IGNORE INTO CashPOSDB.custProdPrice (Cust, Prod, BelongTo)
SELECT Cust, Prod, BelongTo
FROM CashPOSDB.viewertable
To automatically add new rows to custProdPrice, use a trigger:
CREATE TRIGGER addCustProdPrice
AFTER INSERT ON prodTable
FOR EACH ROW
INSERT IGNORE INTO custProdPrice (Cust, Prod, BelongTo)
SELECT c.Cust, NEW.Prod, NEW.BelongTo
FROM custData;

INNER JOIN on One Table but different Parameter

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.

Fetch rows in MySQL which are not present in both columns from another table

There are two tables with details as mentioned below in MySQL:
TABLE 1:
+-------------+---------------+
| user_id | isactive |
+-------------+---------------+
| aaa | 0 |
+-------------+---------------+
| bbb | 0 |
+-------------+---------------+
TABLE 2:
+-------------+---------------+-----------+
|store_no | owner | store |
+-------------+---------------+-----------+
|1234 | aaa | aaa,xyz |
+-------------+---------------+-----------+
|1006 | aaa | aaa |
+-------------+---------------+-----------+
|1005 | ccc | www |
+-------------+---------------+-----------+
I need to fetch rows from table 1 whose entries are neither in 'owner' nor in 'store' column of table 2. For example, in the above scenario, the resultset should contain 'bbb'.
I tried using find_in_set, locate etc but could not fetch the details as required. Please help..
Updated Tables format
Query:
select a.user_id from table1 u
left outer join table2 a
on (owner=user_id or concat(',',store,',') like concat('%,',user_id,',%'))
where (find_in_set(user_id,owner) = 0 or find_in_set(user_id,store) = 0)
and isactive=0
FYI, store column can have concatenated values of more than one userid
You can try using NOT EXISTS
SELECT
T1.user_id
FROM TABLE_1 T1
WHERE NOT EXISTS (
SELECT 1
FROM
TABLE_2 T2
WHERE T2.owner = T1.user_id OR FIND_IN_SET(T1.user_id,T2.store) > 0
);
SQL FIDDLE DEMO
Suggestion:
Is storing a delimited list in a database column really that bad?
You can do it like following :-
SELECT * FROM table1 WHERE user_id NOT IN (SELECT owner FROM table2) AND NOT FIND_IN_SET(user_id, (SELECT store FROM table2));
Second option :-
SELECT * FROM table1 WHERE user_id NOT IN (SELECT owner FROM table2) AND FIND_IN_SET(user_id, (SELECT store FROM table2)) = 0;
It may help you.
I think this should work:
select user_id
from table1
where user_id not in
(select owner from table2)
and not find_in_set(user_id,
(select store from table2)
);

Mysql SELECT - How to select a column as an 'UNSELECTED' column?

I have 2 tables which contain many columns. example of my tables:
table1
_______________________________________________
| a | b | c | d | e | f | g | h | i | ... | z |
-----------------------------------------------
table2
_______________________________________________
| a | b | c | d | e | f | g | h | i | ... | z |
-----------------------------------------------
And now, I want to copy or insert a record from table1 to table 2. This is my query :
INSERT INTO table2
SELECT table1.* FROM table1
WHERE table1.b = '1'
I don't find any errors in query, but all I want is insert a record from all columns except column 'a' in table 1 to table2.
I can do it by this query :
INSERT INTO table2 (b,c,d,...) // it takes a long line
SELECT table1.b,table1.c,table1.d,... FROM table1 // it takes a long line
WHERE table1.b = '1'
But this is not an efficient query line, because i just don't select 1 column.
Is there any efficient way?
You could try duplicating the table with a create like statement, then alter it to drop the columns you don't want and do the insert into select with that new table. Then drop that new table. (or use a temp table)
CREATE TABLE table3 LIKE table1
ALTER TABLE table3 DROP COLUMN x
INSERT INTO table2
SELECT * FROM table3
DROP TABLE table3
and so forth.

Select from table A which does not exist in table B

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