Im sure Im missing something vital here so any advices are welcome. I have one base table lets call it Content_1 and two additional tables called Content_2 and Content_3. What Im trying to do is get all results from table_2 matching the id from table 1 and to add to this result set all results from table_3 which also match the id coming from table_1. Basically to have an OR condition in the final results - return everything from table 2 matching the id from table 1 OR return everything from table 3 matching the id from table 1. However I see that no results are returned so my guess is that we make the first join and then second join is applied to the result set returned after the first join, not on the initial join.
SELECT * FROM Content_1
JOIN Content_2 ON Content_1.id = Content_2.id
JOIN Content_3 ON Content_1.id = Content_3.id
You probably want UNION instead of joining all 3 tables.
SELECT Col1, Col2
FROM Content_1
JOIN Content_2 ON Content_1.id = Content_2.id
UNION
SELECT Col1, Col2
FROM Content_1
JOIN Content_3 ON Content_1.id = Content_3.id
Related
I want to join a bunch of columns from different tables in the same database in mysql. The problem I have, is that not all values are written in the same table.
The concrete example: In one table there is the sid column. Depending on the value in this column the next values I need in this join are located in different tables. If the sid value equals 1 I have to join with table 2 to get the values I want, if the sid value is anything but 1 I have to join with table 3.
I researched a bit into if - else in mysql but all the information I can find is about changing values and how they are displayed under certain conditions.
I want the workflow to change under certain conditions.
No matter which join gets executed, the resulting table has the same amount of columns. I do not actually display any data from table 2 and table 3. The descr column exists in table 4. All the other displayed columns exist in table 1. So there should not be any problems wit the display.
The code looks as follows (inspired by python):
SELECT type, s_type, id, descr
FROM table1
IF sid = 1 THEN
LEFT JOIN table2
ON table1.sid = table2.sid
LEFT JOIN table4
ON table2.sid = table4.id_name
ELSE
LEFT JOIN table3
ON table1.sid = table3.svid
LEFT JOIN table4
ON table3.svid = table4.id_name
END IF;
What is the correct way to get this control flow done in mysql?
IF cannot be used by this in SQL. If I understand the logic, you could do something like this:
SELECT type, s_type, id, table4.descr
FROM table1 LEFT JOIN
table2
ON table1.sid = table2.sid AND table1.sid = 1 LEFT JOIN
table3
ON table1.sid = table3.svid AND table1.side <> 1 LEFT JOIN
table4
ON table4.id_name = COALESCE(table3.svid, table2.sid)
If your tables are large, the COALESCE() might be a performance killer.
I have a problem about query in mysql. I made 2 tables, tables1 and table 2. In table1 there is 2 rows data, its same in table2 where it have 2 rows data, and every table have 3 fields. In this case, I want to make view and this a query :
create view point as select table2.field2 from table1, table2;
I think it will show data in table2 where it have 2 rows data. But the result is showing 4 rows data where every 2 rows is a same data.
When im trying delete 1 row in table1, its mean delete 1 data, and i try input the query like above. The result is correct, its showing 2 rows data in table2. Why it correct when in table1 have 1 row data, and didnt when table1 have 2 rows data. Please how to resolve it? Or its my wrong query.
You are using implicit cross join between these two tables.
Let's say table1 has m rows and table2 has n rows.
Then
SELECT * FROM table1,table2 will return m*n rows.
The above query is equivalent to this:
SELECT * FROM table1 CROSS JOIN table2.
If you want to get all rows from table1 and table2 keeping in mind that I don't want duplicates then you need to use UNION.
So, you might be looking for this query:
CREATE VIEW point AS
SELECT table2.field2 from table2
UNION
SELECT table1.field2 from table1
Note:
If you want to allow duplicate values in your final result set then use UNION ALL instead of UNION like below:
CREATE VIEW point AS
SELECT table2.field2 from table2
UNION ALL
SELECT table1.field2 from table1
I've got two tables related by a field called 'status'. With table2.location having a value of 'texas', there are 20 instances of table2.status having a value of 'good'.
That is, the following query returns 20 rows of table2.status = 'good'.
[A] SELECT table2.status FROM table2 WHERE table2.location = 'texas';
Further, there are 50 unique table1.id's with table1.status = 'good'.
That is, the following query returns 50 rows of unique table1.id's.
[B] SELECT table1.id FROM table1 WHERE table1.status = 'good';
Now, when I run the following query:
[C] SELECT table1.id FROM table1 LEFT JOIN table2 ON table1.status = table2.status WHERE table2.location = "texas";
I would expect it to return the 50 rows of unique id's. However, it is actually returning the 50 rows of unique id's 20 times (ie. I get 1000 rows returned).
The quick fix I did was to simply execute SELECT DISTINCT table1.id... which then just returns one set of 50 rows (not 20 sets of 50 rows).
However, I'd like to know why I'm seeing this behahvior - maybe there is something wrong with my query [C] ?
Thanks!
Your query is wrong if you want to get 50 items: you're performing a cross join 50x20, so you have 1000 records as result.
You cannot join on status (which is not unique): probably your table design is wrong.
IMO you should have id in both tables and join with it...
it is expected. 1st row from table 1 matches 50 rows from table 2, 2nd row from table 1 matches again the same 50 rows from table 2 etc.
Your query has two problems
SELECT table1.id
FROM table1
LEFT JOIN table2 ON table1.status = table2.status
WHERE table2.location = "texas";
First when you usae a left join a condition on the second table must be in the ON clause not the where clause or you convert the left join to an inner join (Since the condition must be met)
So your query should start looking like this:
SELECT table1.id
FROM table1
LEFT JOIN table2
ON table1.status = table2.status
AND table2.location = "texas";
Now your next problem is that status is unlikely to be the thing you actually want to join on. To help you get the results you want though, we would need to see the table structure of the two tables.
Using the following query
select *
from table1
left join table2 on table1.name = table2.name
table1 returns 16 rows and table2 returns 35 rows.
I was expecting the above query to return 16 rows because of the left join, but it is returning 35 rows. right join also returns 35 rows
Why is this happening and how do I get it to return 16 rows?
LEFT JOIN can return multiple copies of the data from table1, if the foreign key for a row in table 1 is referenced by multiple rows in table2.
If you want it to only return 16 rows, one for each table 1 row, and with a random data set for table 2, you can use just a plain GROUP BY:
select *
from table1
left join table2 on table1.name = table2.name
group by table1.name
GROUP BY aggregates rows based on a field, so this will collapse all the table1 duplicates into one row. Generally, you specify aggregate functions to explain how the rows should collapse (for example, for a number row, you could collapse it using SUM() so the one row would be the total). If you just want one random row though, don't specify any aggregate functions. MySQL will by default just choose one row (note that this is specific to MySQL, most databases will require you to specify aggregates when you group). The way it chooses it is not technically "random", but it is not necessarily predictable to you. I guess by "random" you really just mean "any row will do".
Let's assume you have the following tables:
tbl1:
|Name |
-------
|Name1|
|Name2|
tbl2:
|Name |Value |
--------------
|Name1|Value1|
|Name1|Value2|
|Name3|Value1|
For your LEFT JOIN you'll get:
|tbl1.Name|tbl2.Name|Value |
----------------------------
|Name1 | Name1 |Value1|
|Name1 | Name1 |Value2|
|Name2 | NULL | NULL |
So, LEFT JOIN means that all records from LEFT (first) table will be returned regardless of their presence in right table.
For your question you need to specify some specific fields instead of using "*" and add GROUP BY tbl1.Name - so your query will look like
select tbl1.Name, SOME_AGGREGATE_FUNCTION(tbl2.specific_field), ...
from table1
left join table2 on table1.name = table2.name
GROUP BY tbl1.Name
One way to use this is by using the power of SQL distinct.
select distinct tbl1.id, *
from table1 tbl1
left join table2 tbl2 on tbl2.name = tbl1.name
where
....................
Please not that I am also using aliasing.
If the name column is not unique in the tables then you may simply have duplicates on table2.
Try running:
select * from table2 where name not in (select name from table1);
If you get no results back then duplicates on the name column is the reason for the extra rows coming back.
Duplication may be reason. See example in the post
https://alexpetralia.com/posts/2017/7/19/more-dangerous-subtleties-of-joins-in-sql
if you want to join the single latest/earliest relative row from right table, you can limit the join data using min/max primary key and then limiting to 1 row using group Like this:
SELECT * FROM table1
LEFT JOIN (SELECT max(tbl2_primary_col), {table2.etc} FROM table2 GROUP BY name) AS tbl2
ON table1.name = tbl2.name
WHERE {condition_for_table1}
And remember don't use * for left join because it will disable min/max and always return first row.
As per your comment "A random row from table2, as long as name from table1 matches name from table2", you can use the following:
select table1.name, (select top 1 somecolumn from table2 where table2.name = table1.name)
from table1
Note that top 1 is not mysql but it is for SQL Server
The first table have fields:
A_id, B_id, field1, field2
The second table have fields
C_id, A_id, B_id
I want to select all the rows in the first table that contain a B_id that is also present on the second table, moreover, I want only those rows with an specific A_id. I've tried to use JOIN statements, but I can't figure out the correct one. So far I have tried queries like this one, but they don't produce the desired result:
SELECT post.* FROM post INNER JOIN subscription ON subscription.iduser = 22 WHERE post.iduser = 22;
BTW, all of this is on MySQL.
I would write something like :
SELECT post.*
FROM post
LEFT JOIN subscription USING (iduser)
WHERE subscription.iduser = 22
If you have same field names in two tables you join , then JOIN subscription ON subscription.iduser = post.iduser can be written as JOIN subscription USING( iduser ).
Makes code a bit more readable.
update : fixed the typo