I'm trying to construct a select query where it will take all the columns of 4 tables and then order and display the results by the column 'name' (the same in all tables). I'm still learning the ropes of MySQL.
I'm finding that because the columns share the name 'name', only the results from the last table are displayed. Is there a way of performing this query which retains all the data from all the tables?
Should I use different column names? It seems easier to share one name since it is the same information in each.
SELECT * FROM table_one, table_two, table_three, table_four ORDER BY...
The four tables not joined, and the structure is different... Some column names are shared (which it looks like I should fix, I still can at this point), but each has a different amount of columns.
Thank you!
If there's no relationship between the four tables, use UNIONs instead:
SELECT a.name
FROM TABLE_ONE a
UNION
SELECT b.name
FROM TABLE_TWO b
UNION
SELECT c.name
FROM TABLE_THREE c
UNION
SELECT d.name
FROM TABLE_FOUR d
ORDER BY name
There's two options here - UNION is slower, because it will remove duplicates - the final list will be a unique list of names. UNION ALL is faster because it doesn't remove duplicates.
To get the columns from the tables as well, use:
SELECT a.*,
b.*,
c.*,
d.*
FROM (SELECT a.name
FROM TABLE_ONE a
UNION
SELECT b.name
FROM TABLE_TWO b
UNION
SELECT c.name
FROM TABLE_THREE c
UNION
SELECT d.name
FROM TABLE_FOUR d) x
LEFT JOIN TABLE_ONE a ON a.name = x.name
LEFT JOIN TABLE_TWO b ON b.name = x.name
LEFT JOIN TABLE_THREE c ON c.name = x.name
LEFT JOIN TABLE_FOUR d ON d.name = x.name
Yes you should use different column names, but to get all data also you can write quesries like this:
SELECT table_one.* t1, table_two.* t2, table_three.* t3, table_four.* t4 FROM table_one, table_two, table_three, table_four ORDER BY...
johnny_n,
You should use
SELECT name as name1, name as name2, name as name3 etc...
Obviously you need to use the correct syntax, but using the AS keyword, will allow you to use the key you want in your query.
If they all share the same name's....
SELECT *
FROM table_one
LEFT JOIN
table_two USING(name)
LEFT JOIN
table_three USING(name)
LEFT JOIN
table_four USING(name)
ORDER BY name
Related
I am trying to join my master table to some sub-tables in PostgreSQL in a single select query. I am getting a syntax error and I have the feeling I am making a terrible mistake or doing something which is not allowed. The code:
Select
id,
length,
other_stuff
from my_table tbl1
Left join
(
Select
id,
height
from my_table2 tbl2) tbl2 using (id)
left join
-- I get syntax error here
(
With a as (select id from some_table),
b as (Select value from other_table)
Select id, value from a, b) tbl3 using (id)
order by tbl1.id
Can we use WITH clause in left joins sub or nested queries and Is there a better way to do this?
UPDATE1
Well, I would like to add some more details. I have three select queries like this (having unique ID) and I want to join them based on ID.
Query1:
With a as (Select id, my_other records... from postgres_table1)
b as (select id, my_records... from postgres_table2)
c as (select id, my_record.. from postgres_table3, b)
Select
id,
my_records
from a left join c on some_condtion_with_a
order by 1
Second query:
Select
id, my_records
from
(
multiple_sub_queries_by_getting_records_from_c
)
Third Query:
With d as (select id, records.. from b),
e as (select id, records.. from d),
f as (select id, records.. from e)
select
id,
records..
from f
I tried to join them using left join. The first two queries were joined successfully. While, joining third query I got the syntax error. Maybe, I am complicating things thus I asked is there a better way to do it.
You are over complicating things. There is no need to use a derived table to outer join my_table2. And there is no need for a CTE plus a derived table to join the tbl3 alias:
Select id,
length,
other_stuff
from my_table tbl1
Left join my_table2 tbl2 using (id)
left join (
select st.id, ot.value
from some_table st
cross join other_table ot
) tbl3 using (id)
order by tbl1.id;
This assumes that the cross join you create with Select id, value from a, b is intended.
Not tested, but I think you need this. try:
with a as (select id from some_table),
b as (Select value from other_table)
Select
id,
length,
other_stuff
from my_table tbl1
Left join
(
Select
id,
height
from my_table2 tbl2
)
tbl2 using (id)
left join
(
Select id, value from a, b
)
tbl3 using (id)
order by tbl1.id
I've only ever seen/used WITH in the following format:
WITH
temptablename(columns) as (query),
temptablename2(columns) as (query),
...
temptablenameX(columns) as (query)
SELECT ...
i.e. they come first
You'll probably find it easier to write queries if you use indentation to describe nesting levels. I like to make my SELECT FROM WHERE GROUPBY ORDERBY at one indent level, and then tablename INNER JOIN ON etc more indented:
SELECT
column
FROM
table
INNER JOIN
(
SELECT subcolumn FROM subtable WHERE subclause
) myalias
ON
table.id = myalias.whatever
WHERE
blah
Organising your indents every time you nest down a layer really helps. By making everything that is "a table or a block of data like a table (i.e. a subquery)" indented the same amount you can easily see the notional order that the DB should retrieve
Move your WITHs to the top of the statement, you will still use the alias names in place in the sub sub query of course
Looking at your query, there isn't much point in your subqueries.. You don't do any grouping or particularly complex processing of the data, you just select an ID and another column and then join it in. Your query will be simpler if you don't do this:
SELECT
column
FROM
table
INNER JOIN
(
SELECT subcolumn FROM subtable WHERE subclause
) myalias
ON
table.id = myalias.whatever
WHERE
blah
Instead, do this:
SELECT
column
FROM
table
INNER JOIN
subtable
ON
table.id = subtable.id
WHERE
blah
Re your updated requirements, following the same pattern.
look for --my comments
With a as (Select id, my_other records... from postgres_table1)
b as (select id, my_records... from postgres_table2)
c as (select id, my_record.. from postgres_table3, b)
d as (select id, records.. from b),
e as (select id, records.. from d),
f as (select id, records.. from e)
SELECT * FROM
(
--your first
Select
id,
my_records
from a left join c on some_condtion_with_a
) Q1
LEFT OUTER JOIN
(
--your second
Select
id, my_records
from
(
multiple_sub_queries_by_getting_records_from_c
)
) Q2
ON Q1.XXXX = Q2.XXXX --fill this in !!!!!!!!!!!!!!!!!!!
LEFT OUTER JOIN
(
--your third
select
id,
records..
from f
) Q3
ON QX.XXXXX = Q3.XXXX --fill this in !!!!!!!!!!!!!!!!!!!
It'll work, but it might not be the prettiest or most necessary SQL arrangement. As both i and HWNN have said, you can rewrite a lot of these queries where you're just doing some simple selecting in your WITH.. But likely that theyre simple enough that the database optimizer can also see this and rerwite the query for you when it runs it
Just remember to code clearly, and lay your indentation out nicely to stop it tunring into a massive, unmaintainable, undebuggable spaghetti mess
This is a part of my query and I have a union before this query. I want to select more column in table1 under a condition.
SELECT c.ID, c.Name, c.Position, c.Email, c.ContactNumber
FROM table1 c
INNER JOIN table2 a
ON c.ID = (SELECT foreignID FROM table2 WHERE a.Name = 'someName')
WHERE Dept = 'Something' --this will return nothing since in the inner join
--the condition returns a single column and it doesn't
--satisfy the WHERE Clause
I want to select the person that satisfies the ID (which works), including the people with a Dept of Something. Is there another way in solving this, or I really need to use UNION for this. Will this affect the performance of an App, specifically Mobile App?
If I Understood your requirement correctly then Use LEFT JOIN
SELECT c.ID, c.Name, c.Position, c.Email, c.ContactNumber
FROM table1 c
LEFT JOIN table2 a ON c.ID = a.foreignID AND a.Name = 'someName'
WHERE Dept = 'Something'
I need union more than one table in a select's join clause,given below is a sample
select .. ...
from table_a inner join (/*here i want to join two tables(ex. table_c and table_b)*/ ) -- not i am using left join also which is in another condition
where /*some condtitions*/
how this is possible ?
Do you mean that you want to do this?
select ...
from table_a join
(select ... from table_b
union
select ... from table_c) t on table_a.col = t.col
That sort of thing?
JOIN is a binary operator, so you may join two tables or views at a time. In order to join three tables, you can join two of them and then join the result with the third one.
It's like addition: to sum up three numbers, you add the second to the first, and then add the third to the result.
select * from
table_a a
inner join
table_b b on a.id= b.id
inner join
table_c c on b.id= c.id
where /*some conditions*/;
I have two tables
Table A
-------
ID
ProductName
Table B
-------
ID
ProductID
Size
I want to join these two tables
SELECT * FROM
(SELECT * FROM A)
LEFT JOIN
(SELECT * FROM B)
ON A.ID = B.ProductID
This is easy, I will get all rows from A multiplied by rows matched in B, and NULL fields if there is no match.
But here comes the tricky question, how can I get all rows from A with NULL fields for table B, even if there is a match, so I get an extra line with NULL values plus all the matches?
SELECT A.*
, B3.ID
, B3.ProductID
, B3.Size
FROM A
LEFT JOIN
(
SELECT ProductID as MatchID
, ID
, ProductID
, Size
FROM B
UNION ALL
SELECT ID
, null
, null
, null
FROM A A2
) B3
ON A.ID = B3.MatchID
Live example at SQL Fiddle.
Instead of using UNION ALL in a subquery as suggested by others, you could also (and I would) use UNION ALL at the outer level, which keeps the query simpler:
SELECT A.ID, A.ProductName, B.ID, B.Size
FROM A
INNER JOIN B
ON B.ProductID = A.ID
UNION ALL
SELECT A.ID, A.ProductName, NULL, NULL
FROM A
Since every join is going to be successful, we can switch to a full/inner join:
SELECT
*
FROM
A
INNER JOIN
(SELECT ID,ProductID,Size FROM B
UNION ALL
SELECT NULL,ID,NULL FROM A) B
ON
A.ID = B.ProductID
Now would be a very good time to switch to naming columns explicitly, rather than using SELECT *
Or, if, as per #Andomar's comment, you need all of the B columns to be NULL:
SELECT
A.ID,A.ProductName,
B.ID,B.ProductID,B.Size
FROM
A
INNER JOIN
(SELECT ID,ProductID,Size,ProductID as MatchID FROM B
UNION ALL
SELECT NULL,NULL,NULL,ID FROM A) B
ON
A.ID = B.MatchID
In my query I want to get the rows from two different tables descending by their primary keys. They have two different keys so is it possible to be able to do this in one query?
Your question is a little vague. To "get rows from two different tables" you can do a JOIN, or you can do a UNION.
In the case of a JOIN:
SELECT a.id, a.something, b.id, b.something
FROM a
INNER JOIN b ON b.aId = a.id
ORDER BY a.id, b.id
In the case of a UNION:
SELECT id, something
FROM (
SELECT a.id. a.something FROM a
UNION
SELECT b.id, b.something FROM b
) t
ORDER BY t.id
These are very different, but it seems like one of them will meet your needs.
(Note that UNION by default eliminates duplicates. Use UNION ALL to keep duplicates.)
SELECT *
FROM ( select a.pk, a.foo, a.bar from a
union
select b.pk, b.foo, b.bar from b
) c
ORDER BY c.pk DESC;