MySql select by excluding all id from another table - mysql

I would like to select data from a table which looks like
ID|FOO|CITY|BAR
there is another table where all data which has been selected yet will be stored so that I get unique results. This table looks like
ID|ID_from_other_table
Now I'm stucking if I either should use a left join or a union?
Which one is faster and, how can I set this up the correct way?

left join would be probably faster in MySQL rather than other anti-join patterns like not in and not exists.
select t1.*
from table1 t1
left join table2 t2 on t1.id = t2.id_from_other_table
where t2.id is null

Related

Specify table-column on "in" operator

i would like to know if there is any shortcut to specify the column where IN have to check for matches.
Example:
Instead of this:
select *
from table1
where id in(
select column
from table2
)
something like this:
select *
from table1
where id in table2.column
I know the existence of TABLE for IN, ANY, SOME to specify a table, but it works only if the table specified is composed by just 1 column
EDIT: using join is not an option, because the real use i was looking for is on a NOT IN operator, and also JOIN create duplicates sometimes like in a one to many relation
There is no shortcut like that in SQL. Let me explain why.
In a query, all table references need to be made in the FROM clause. Hence, you cannot simply refer to table2.col unless table2 has been defined in the FROM clause. table2 is actually an alias, which defaults to the table name.
From a performance perspective, I would recommend exists:
select t1.*
from table1 t1
where exists (select column
from table2 t2
where t2.column = t1.id
)
In particular, this can take advantage of an index on table2(column) and has the same semantics as in.
Using a JOIN is a bit shorter. At least it does not require a subquery or another SELECT ... FROM.
SELECT table1.*
FROM table1
JOIN table2 ON table1.id = table2.column
Although this simple example is an inner join, not a semi-join. An inner join is different because it produces one row per matched row in table2. A semi-join only produces one row for each row in table1, even if it matches multiple rows in table2.
If you want to simulate a semi-join, use DISTINCT to reduce the result to one row per row of table1:
SELECT DISTINCT table1.*
FROM table1
JOIN table2 ON table1.id = table2.column
If you want to check for something like NOT EXISTS, use an exclusion join:
SELECT table1.*
FROM table1
LEFT OUTER JOIN table2 ON table1.id = table2.column
WHERE table2.column IS NULL
No need to use DISTINCT on the outer join example. There will be no row duplication from the join, because it can only "match no rows" once.

How to do a join on 2 tables, but only return the data for one table?

I am not sure if this is possible. But is it possible to do a join on 2 tables, but return the data for only one of the tables. I want to join the two tables based on a condition, but I only want the data for one of the tables. Is this possible with SQL, if so how? After reading the docs, it seems that when you do a join you get the data for both tables. Thanks for any help!
You get data from both tables because join is based on "Cartesian Product" + "Selection". But after the join, you can do a "Projection" with desired columns.
SQL has an easy syntax for this:
Select t1.* --taking data just from one table
from one_table t1
inner join other_table t2
on t1.pk = t2.fk
You can chose the table through the alias: t1.* or t2.*. The symbol * means "all fields".
Also you can include where clause, order by or other join types like outer join or cross join.
A typical SQL query has multiple clauses.
The SELECT clause mentions the columns you want in your result set.
The FROM clause, which includes JOIN operations, mentions the tables from which you want to retrieve those columns.
The WHERE clause filters the result set.
The ORDER BY clause specifies the order in which the rows in your result set are presented.
There are a few other clauses like GROUP BY and LIMIT. You can read about those.
To do what you ask, select the columns you want, then mention the tables you want. Something like this.
SELECT t1.id, t1.name, t1.address
FROM t1
JOIN t2 ON t2.t1_id = t1.id
This gives you data from t1 from rows that match t2.
Pro tip: Avoid the use of SELECT *. Instead, mention the columns you want.
This would typically be done using exists (or in) if you prefer:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 on t2.x = t1.y);
Although you can use join, it runs the risk of multiplying the number of rows in the result set -- if there are duplicate matches in table2. There is no danger of such duplicates using exists (or in). I also find the logic to be more natural.
If you join on 2 tables.
You can use SELECT to select the data you want
If you want to get a table of data, you can do this,just select one table date
SELECT b.title
FROM blog b
JOIN type t ON b.type_id=t.id;
If you want to get the data from two tables, you can do this,select two table date.
SELECT b.title,t.type_name
FROM blog b
JOIN type t ON b.type_id=t.id;

Select everything from joined tables

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

SQL: How can we make a table1 JOIN table2 ON a table given in a field in table1?

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

How to retrieve non-matching results in mysql

I'm sure this is straight-forward, but how do I write a query in mysql that joins two tables and then returns only those records from the first table that don't match. I want it to be something like:
Select tid from table1 inner join table2 on table2.tid = table1.tid where table1.tid != table2.tid;
but this doesn't seem to make alot of sense!
You can use a left outer join to accomplish this:
select
t1.tid
from
table1 t1
left outer join table2 t2 on
t1.tid = t2.tid
where
t2.tid is null
What this does is it takes your first table (table1), joins it with your second table (table2), and fills in null for the table2 columns in any row in table1 that doesn't match a row in table2. Then, it filters that out by selecting only the table1 rows where no match could be found.
Alternatively, you can also use not exists:
select
t1.tid
from
table1 t1
where
not exists (select 1 from table2 t2 where t2.tid = t1.tid)
This performs a left semi join, and will essentially do the same thing that the left outer join does. Depending on your indexes, one may be faster than the other, but both are viable options. MySQL has some good documentation on optimizing the joins, so you should check that out..