SQL insert into table from two tables - mysql

Let say I have a table: table3 and I want to insert values from table1 and table2 into table3
table1: Columns: hID hName
table2: Columns: aID aName
table3: Columns: hID aID
I want to insert table1 hID and table2 aID into table3 How would I do that?
my current query uses an inner join to attempt to join table1 and table2 but table1 and table2 don't share a common column, so how do I this?
my query:
INSERT INTO table3 (hID, aID)
SELECT hID
FROM table1 as t1
INNER JOIN table2 as t2 ON ??;

Your question is rather artificial since relational databases rarely join tables in this manner. It is, however, possible to do so, even with uneven data sets. You can use ROW_NUMBER() to generate an mock value that you can use to join both tables.
For example:
with
l as (select hID, row_number() over() as rn from table1),
r as (select aID, row_number() over() as rn from table2)
select l.hID, r.aID from l left join r on r.rn = l.rn
union
select l.hID, r.aID from l right join r on r.rn = l.rn
If the left values are 1, 2, 3, 5, and 7, and the right values are 101, 200, and 555, the result it produces is (in no particular order):
hID aID
---- ----
1 101
2 220
3 555
5 null
7 null
See running example at DB Fiddle.
Note: The query could be simpler if MySQL implemented FULL JOIN. Unfortunately it doesn't so it needs to be simulated.

Related

Joining 2 tables SQL

I m trying to fetch data from 2 table aisle and type. The aisle table has following construct:
aisle_id | name | x | y
and the type table has following construct
type_id | name | aisle_id (FK)
aisle_id is the foreign key.
I'm using this sql query which works but, not as expected:
SELECT NAME,X, Y FROM type, aisle where Name ="bread"
What this statement returns me is, it returns bread but also returns all the data from the X and Y, which i do not want, I just want the x and y related to bread. So could anyone help?
Thank you
Try joining the two on aisle_id as below:
SELECT t.Name, a.X, a.Y
FROM aisle a INNER JOIN type t
ON a.aisle_id = t.aisle_id
WHERE a.Name ="bread"
With a simple Google search, and since you know what you need (join), the first result came directly from MySQL documentation:
Some join examples:
SELECT * FROM table1, table2;
SELECT * FROM table1 INNER JOIN table2 ON table1.id=table2.id;
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
SELECT * FROM table1 LEFT JOIN table2 USING (id);
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
LEFT JOIN table3 ON table2.id=table3.id;
In your case it would be:
SELECT aisle.NAME, aisle.X, aisle.Y FROM type JOIN aisle ON type.type_id = aisle.type_id WHERE aisle.Name ="bread"

SQL - joining data

Is it possible to get 1 result where I require data from 3 tables.
First table: I will need to grab all the fields (1 row found by a primary key)
Second table: I will need to grab the field 'username' (connected to first table by 'master_id')
Third table: I will need to grab the latest added row with the associated master_id key (table has 'date', 'master_id', 'previous_name').
select top 1 first.*, second.username, third.*
from first
inner join second on first.id = second.master_id
inner join third on first.id = third.master_id
order by
third.date desc
As always there are dozens of ways to skin a cat, I'm not sure if this is optimized as the subquery methods, but it should work.
You can join the three tables together. Then, you can use a "filter" join to keep only the latest Table3 row:
select *
from Table1 t1
join Table2 t2
on t2.master_id = t1.master_id
join Table3 t3
on t3.master_id = t1.master_id
join (
select master_id
, max(date) as max_date
from Table3
group by
master_id
) as filter
on t3.master_id = filter.master_id
and t3.date = filter.max_date
You'll need a correlated subquery for that third table.
SELECT t1.*, username, date, previous_name
FROM FirstTable t1
INNER JOIN SecondTable t2 ON t1.master_id=t2.master_id
INNER JOIN
(SELECT master_id, date, previous_name
FROM ThirdTable AS t3_1
WHERE date = (
SELECT MAX(date)
FROM ThirdTable AS t3_2
WHERE t3_2.master_id=t3_1.master_id)) q1 ON q1.master_id=t1.master_id;
NOTE: Untested.

MySQL select fields in one table that are not in another table

I have 2 tables in a MySQL DB:
Table 1 : id, galleryname
Table 2 : galleryid, <many other fields...>
Using PHP, I need to select all rows in Table 1 based on its ID where that id (galleryid) does not appear in Table 2.
Example:
Table 1
1, flowers
2, water
3, mountains
4, winter
Table 2
3, ...
would return these rows from Table 1
1, flowers
2, water
4, winter
I'm not exactly sure how to go about this. I am pretty good at the basics of MySQL but I suspect this is a JOIN or a UNION that is out of my league.
Any help is appreciated.
Try this:
SELECT * FROM table1
WHERE id NOT IN
(SELECT galleryid FROM table2)
or
SELECT * FROM table1
LEFT JOIN table2
ON table1.id = table2.galleryid
WHERE table2.galleryid IS NULL
Left join brings all the t1 records, then filter out those that have t2.galleryid NULL (no records in t2)
SELECT id, galleryname
FROM table1 AS t1
LEFT OUTER JOIN table2 AS t2 ON t1.id = t2.galleryid
WHERE t2.galleryid IS NULL
SELECT * FROM table1
LEFT JOIN table2
ON table1.id = table2.galleryid
WHERE table2.galleryid IS NULL
Someone posted an answer (then deleted it) that gave me ONLY the record that was in both. All others here seemed to give errors but using that original post I made one change and it worked.
Original:
SELECT * FROM table1 INNER JOIN table2 ON galleries.id = images.galleryid
(this gave me just the one that was in both)
Adding the !:
SELECT * FROM table1 INNER JOIN table2 ON galleries.id != images.galleryid
(this gave me what I needed)

mysql - two left joins - double counting

Long time user, first time poster. I've found similar questions/answers, typically involving subqueries, but I'm not sure how to apply to my situation.
I have 3 tables:
table1
id
table2
id | val (each id has 1 of 3 possible values)
table3
id | val (each id has 1 of 3 possible values)
EDIT: Example: (table1 = unique id of everyone who attended a theme park; table2 = which attraction each visitor visited first; table3 = which attraction each visitor visited second).
I want to write a query to look up 7 different counts:
(1) count of the unique ids in table1
(2) count of the number of ids that have each of the possible values in table2
(3) count of the number of ids that have each of the possible values in table3
My MySQL query:
SELECT
count(DISTINCT table1.id) AS x1,
SUM(IF(table2.val='1'),1,0)) AS x2,
SUM(IF(table2.val='2'),1,0)) AS x3,
SUM(IF(table2.val='3'),1,0)) AS x4,
SUM(IF(table3.val='1'),1,0)) AS x5,
SUM(IF(table3.val='2'),1,0)) AS x6,
SUM(IF(table3.val='3'),1,0)) AS x7
FROM
table1
LEFT JOIN
table2 ON table1.id=table2.id
LEFT JOIN
table3 ON table1.id=table3.id
Results:
x1 = correct (because of DISTINCT)
x2,x3,x4 = correct
x5,x6,x7 = TWICE the number they should be (because I'm getting cartesian product?)
Any suggestions?
You are getting a Cartesian result. Since you are not showing how many "1", "2" or "3" counts per "ID", just do a select sum() from those tables by themselves. Since a sum with no group by will always result in ONE record, you don't need any join and it will pull the results of one record per each summary with no Cartesian result. Since your original query was LEFT JOIN to the others, the ID would have already existed on table 1, so why re-query count distinct in each sub-table.
SELECT
SumForTable1.x1,
SumForTable2.x2,
SumForTable2.x3,
SumForTable2.x4,
SumForTable3.x5,
SumForTable3.x6,
SumForTable3.x7
FROM
( select count(DISTINCT table1.id) AS x1
from table1 ) SumForTable1,
( select SUM(IF(table2.val='1'), 1, 0)) AS x2,
SUM(IF(table2.val='2'), 1, 0)) AS x3,
SUM(IF(table2.val='3'), 1, 0)) AS x4
from table2 ) SumForTable2,
( select SUM(IF(table3.val='1'), 1, 0)) AS x5,
SUM(IF(table3.val='2'), 1, 0)) AS x6,
SUM(IF(table3.val='3'), 1, 0)) AS x7
from table3 ) SumForTable3
My guess is you issue is that id is not unique in table1. So even though it is unique in table2/3 (according to your description) each row in table2/3 is joined to two rows in table1 and thus counted twice. Has nothing to do with the left joins, normal inner joins would have the same issue.
If mysql (which I don't know real well) lets you do inline views like oracle does, then you can fix it by writing your query as:
SELECT
count(view1.id) AS x1,
SUM(IF(table2.val='1'),1,0)) AS x2,
SUM(IF(table2.val='2'),1,0)) AS x3,
SUM(IF(table2.val='3'),1,0)) AS x4,
SUM(IF(table3.val='1'),1,0)) AS x5,
SUM(IF(table3.val='2'),1,0)) AS x6,
SUM(IF(table3.val='3'),1,0)) AS x7
FROM
( SELECT DISTINCT table1.id
FROM table1
) view1
LEFT JOIN
table2 ON view1.id=table2.id
LEFT JOIN
table3 ON view1.id=table3.id
I'd remove duplicates on every table:
SELECT
count(t1.id) AS t1,
SUM(IF(t2.val=1,1,0)) AS t21,
SUM(IF(t2.val=2,1,0)) AS t22,
SUM(IF(t2.val=3,1,0)) AS t23,
SUM(IF(t3.val=1,1,0)) AS t31,
SUM(IF(t3.val=2,1,0)) AS t32,
SUM(IF(t3.val=3,1,0)) AS t33
FROM (SELECT DISTINCT * FROM table1) as t1
JOIN (SELECT DISTINCT * FROM table2) as t2 ON t1.id=t2.id
JOIN (SELECT DISTINCT * FROM table3) as t3 ON t1.id=t3.id;

Merge 3 structurally identical tables if value in date column exists in all 3

I have a mysql db/server that has 3 tables that are identical in structure:
west, midwest and east.
I would like to create a national table with the sum of the columns of those regional tables, ONLY if the datetime row matches all 3 tables. That way if one hour is missing in a particular table, I don't end up summing 2 regions and calling it national.
Here is how I am thinking to do it:
All 3 tables have a datetime column.
Merge the tables (union?) only if the datetime row exists in all 3 tables.
Aggregate (sum) the columns grouped by datetime column. I would of course be summing all columns which carry int values.
I am not sure how to run a query that would perform this task.
These tables have 11mil rows so an efficient way would be great.
I am also open to other approaches to solve this problem.
I picked the answer from Neil because although the answer would not work if datetime col is not unique i.e. multiple rows in Table1 with the same datetime. Using any other method the performance I got was horrific, hours of query time. I decided to compromise. I created 3 new tables
westh, midwesth and southh.
These 3 new tables are a creation of aggregating the original tables by hour.
I then used Neils second version with a twist:
INNER JOIN Table2 USING (datetime)
While datetime is indexed in my tables that provides superior performance which is a firm criteria for me.
First version:
SELECT T123.dtcol, SUM(T123.intcol) AS intcolsum
FROM (
SELECT Table1.dtcol, Table1.intcol FROM Table1
UNION
SELECT Table2.dtcol, Table2.intcol FROM Table2
UNION
SELECT Table3.dtcol, Table3.intcol FROM Table3
) T123
GROUP BY T123.dtcol
HAVING COUNT(*) = 3
Second version:
SELECT Table1.dtcol, Table1.intcol + Table2.intcol + Table3.intcol AS intcolsum
FROM Table1 T1
INNER JOIN Table2 T2 ON T2.dtcol = T1.dtcol
INNER JOIN Table3 T2 ON T3.dtcol = T1.dtcol
use
SELECT A.dtcol, SUM (A.intcol) intcolsum FROM
(
SELECT 'T1' T, T1.* FROM Table1 T1
UNION
SELECT 'T2' T, T2.* FROM Table2 T2
UNION
SELECT 'T3' T, T3.* FROM Table3 T3
) A
WHERE A.dtcol IN
(
SELECT T1.dtcol
FROM Table1 T1
INNER JOIN Table2 T2 ON T2.dtcol = T1.dtcol
INNER JOIN Table3 T2 ON T3.dtcol = T1.dtcol
)
GROUP BY A.dtcol