I am using mySQL 5.6. I have two tables: t1 and t2. Both have many columns. And many columns in t1 and t2 share the same name: for example, there is a "var1" column in t1 and in t2.
I want to join the tables, selecting (a) all columns from t1 and (b) only the columns in t2 that have names that don't appear in t1. For example, I would not select "var1" from t2.
Here is a valid mySQL command that does not work because some columns share the same name:
SELECT * FROM t1 LEFT JOIN t2 ON (t1.ID=t2.ID);
MySQL sensibly returns this error message:
ERROR 1060 (42S21): Duplicate column name 'var1'
So I want to run a command like
SELECT t1.*, DISTINCTCOLUMNS(t2.*) FROM t1 LEFT JOIN t2 ON (t1.ID=t2.ID);
Except, of course, that there is no DISTINCTCOLUMNS operation in SQL. But is there a similar (real) command that will achieve the same effect?
I see that common advice is to avoid SELECT * syntax, partly for efficiency purposes. I appreciate that, but I do not want to write out the names of all of the columns that I need.
The real issue here is you have the same column name for both tables. So you need to alias your columns.. This is also why you shouldn't just pull all columns out but the specific ones you need..
SELECT t1.ID as t1_id,
t1.var1 as t1_var1,
t2.ID as t2_id,
t2.var1 as t2_var1,
... Etc.
FROM t1
LEFT JOIN t2 on t1.ID = t2.ID
With two ID columns and no way to distinguish between the two an error will occur
You could qualify the columns like
SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.ID=t2.ID);
But you should not do it unless the columns with identical names do actually hold/reference the same data.
try like following. this may help you
SELECT t1.*, t2.YourDesiredColumnName FROM t1 LEFT JOIN t2 ON (t1.ID=t2.ID);
Related
I have two joined tables:
SELECT table1.*, table2.* FROM table1 t1 INNER JOIN table2 t2 ON t1.id = t2.t1_id
The question: In query results, id will always be taken from secondary table defined in SELECT statement?
For example:
if I use select t1.*, t2.* - in results id will be t2.id
if I use select t2.*, t1.* - id will be t1.id.
Is this good practice to use 'merged' result, or should I avoid ambiguity, and always define columns strictly?
No, the sql query will return all columns with the same name from all tables, not just the last one, unless you use a natural join (table1 inner join table2 using(column)).
If you use some kind of a component that stores the results in associative arrays, then these components usually use only the field names as key, therefore they return only the last column's value from those that have the same name.
However, it is a good practive to use an alias if you want to return more than 1 column that has the same name in the database.
My suggestion is to use tablename with alias and get to use like this. It would be best practice to run query.Mention your column names even though it has many columns. You can order your display.
SELECT t1.columnName1, t2.columnName2 FROM tablename1 t1 INNER JOIN tablename2 t2 ON t1.id = t2.id
I have a simple task in MySQL. I have two tables t1 and t2. Table t1 has one column in common with table t2.
What I want is to return all the columns from both tables (order is not important) but making sure that the rows of both tables are matching based on a common field, say fieldx. However, not all the rows in table t1 have a matching row in table t2 (i.e. table t1 has much more rows, but all rows in t2 have a matching row in t1 ).
I tried to use where as such:
SELECT t1.* t2.* from t1, t2 where t1.fieldx=t2fieldx
However this returns only the number of rows as there are in table t2.
I also tried right and left joins, but couldn't get that to work either (this way not all columns of both tables were included..)
How would I do this?
The LEFT JOIN will give you all the rows from t1 and if t2 does not have an entry for it, t2 columns will appear as NULL:
SELECT t1.*,
t2.*
FROM t1
LEFT JOIN t2
ON t1.fieldx = t2.fieldx
Here is an Live DEMO of the above said, as you can see in t2, I've only referenced the first 3 records of t1 hence why the rest of the t2 information comes out NULL, as there is no t2 record to that given t1 entry.
I want is to return all the columns from both tables (order is not
important) but making sure that the rows of both tables are matching
based on a common field, say fieldx.
This query solve this:
SELECT t1.* t2.* FROM t1 INNER JOIN t2 WHERE t1.fieldx = t2fieldx
Further, if the next phrase is true, you can try with LEFT OUTER JOIN too (or RIGHT).
but all rows in t2 have a matching row in t1
SELECT t1.* t2.* FROM t2 LEFT OUTER JOIN t1 WHERE t1.fieldx = t2fieldx
What I am trying to do is join two tables, lets call them t1 and t2 on two columns. id and name, for this example. t1 will always have id and name, but t2 won't always have id and name. t1 has more columns like viewes, reports, and t2 has other columns that need to be joined. My question is, how can I show 0's for t2's columns if they don't exist?
I hav something similar to this, that joins tables only if both tables' rows have some value.
SELECT
date(t1.start_time) date,
t1.name,
t1.viewes,
t1.reports,
t2.col5,
t2.col6
from
table1 t1
left outer join table2 t2
on t2.name = t1.name and date(t2.start_time) = date(t1.start_time)
group by
1,2
order by
1 desc,
2 asc
;
I have lot's of experience with MySQL, but sometimes find that things need to be hacked to work correctly. What's your suggestion for this problem?
Say I've two tables - "Table1" and "Table2" in my MySQL database.
"id" primary key (auto_increment) in "Table1" is the reference key in "Table2" - "tab_id".
There could be zero or more "Table2" rows for one "Table1" row.
Now I'm trying to do a search on one of the column in "Table2" say "email" column OR on one of the column in "Table1" say "address" and print "Table1" row values.
I see there are 3 possibilities:
1. Join
2. Sub-Query
3. Union
1 Join
SELECT *
FROM Table1 t1, Table t2
WHERE t1.id = t2.tab_id
AND (t1.address like '%str%' OR t2.email like '%str%');
-- This works fine, but when there are no rows in "Table2" relevant to "Table1" .. the JOIN will fail, hence output is in-consistent.
2 Sub-Query
SELECT *
FROM Table1 t1
WHERE t1.address like '%str%'
OR t1.id IN (SELECT t2.tab_id
FROM Table2 t2
WHERE t2.email like '%str%');
-- This works fine, but when there are two manys rows in "Table2" (say 5K) the query goes very slow :(
3 Union
SELECT 'relevant_columns'
FROM Table1 t1, Table t2
WHERE t1.id = t2.tab_id
AND (t1.address like '%str%' OR t2.email like '%str%')
UNION
SELECT 'relevant_columns'
FROM Table1 t1
WHERE t1.address like '%str%'
ORDER BY relevant_column
-- This works fine, may be create a view with a similar UNION, does the job.
Now, my question what is the correct way ... is it okay to call a UNION always?
MySQL Engine: MyISAM
SELECT *
FROM Table1 t1
LEFT JOIN Table t2 ON t2.tab_id = t1.id
WHERE t1.address like '%str%'
OR t2.email like '%str%';
You need to do a LEFT JOIN. When you make a FROM from two tables as you did, it works as an INNER JOIN (or a CROSS JOIN if there is no WHERE clause), which means that the output shows only rows that have a match in both tables. With LEFT JOIN you said that you want all rows from the left table (t1) with the matched row on the right table (t2). If there is no match in t2, then null is used.
You can use sub-query, but as you can see it is not the best choice
An UNION here does not give you any advantage. An UNION is useful to merge together datasets with same columns.
Edit
If you have issues with JOIN, because some Table1 rows do not appear, then you need a LEFT JOIN. The fact that takes a long time, is another problem. Those tables are not big at all, so I guess you need to do some index work on those tables.
If you want help about the union you need to tell me which are those relevant_columns, because they must have the same number of columns, same type and same sequence.
You might optimize the union without joins, depending on what you want to output when t2.email has a match. Here is an example
SELECT t1.id, t1.address, null as email
FROM Table1 t1
WHERE t1.address like '%str%'
union
SELECT t2.tab_id as id, null as address, t2.email
FROM Table t2
WHERE t2.email like '%str%';
SELECT *
FROM Table1 t1
LEFT JOIN Table2 t2
ON t1.id = t2.tab_id
WHERE t1.address like '%str%' OR t2.email like '%str%';
Imagine I have table1 which has a column named 'table_name'. I use table1.table_name to store the name of another table in the database. The referenceable tables would all have a field 'target_id.
Is is possible to use table_name in a JOIN statement?
For example:
SELECT t1.*, t2.* FROM table1 AS t1
JOIN table1.table_name AS t2 ON t1.table1_id = t2.target_id
The obvious solution is to use the script (C++ in my case) to get the table name first, and construct a SQL query from it. The question is: can we bypass the script and do this directly in SQL (MySQL)?
Edit: What is dynamic SQL?
The only chance you have is to do 2 SQL statements:
select the tablename you need
use this table-name to dynamically build the secound query to get the data you need - what you want isn't possible to do with SQL directly (and it sounds like you've designed your database wrong in some way - but that's hard to say without knowing what's the goal of it).
I know I'm late to the party, but I wanted to offer a different solution. I see this sort of thing a lot in audit tables. The column table_name would refer to "what table was changed" and table1_id would refer to the ID of the row that changed in that table. In this case, the audit table is pointing back to many different tables that don't normally get joined.
Here goes:
SELECT t1.*, t2.*, t3.*, t4.*, t5.*
FROM table1 AS t1
left JOIN table2 AS t2
ON t1.table1_id = t2.target_id
and t1.table_name = 'table2'
left JOIN table3 AS t3
ON t1.table1_id = t3.target_id
and t1.table_name = 'table3'
left JOIN table4 AS t4
ON t1.table1_id = t4.target_id
and t1.table_name = 'table4'
left JOIN table5 AS t5
ON t1.table1_id = t5.target_id
and t1.table_name = 'table5'
Of course, the main drawback is that each table that can be possibly referenced needs to be explicitly included in the SQL command.
You can get more elegant output using this as your select list:
SELECT
t1.*,
coalesce(t2.fieldA, t3.fieldA, t4.fieldA, t5.fieldA) as fieldA,
coalesce(t2.fieldB, t3.fieldB, t4.fieldB, t5.fieldB) as fieldB
etc