INNER JOIN ON IF statement results - mysql

table2.A = 1 for display only
table2.B = 2 for display only
SELECT * FROM table1
INNER JOIN table2 ON
IF(A > B)
table2.id = table1.id -- if value of A is > B then inner join table on table2.id = table1.id
ELSE IF (A < B)
table2.id = table1.somethingElse -- if value of A is < B then inner join table on table2.id = table1.somethingElse
How can i translate this into actual SQL?

Use AND/OR logic in the ON clause:
SELECT *
FROM table1 t1
INNER JOIN table2 t2
ON (t2.A > t2.B AND t1.id = t2.id) OR
(t2.A < t2.B AND t1.somethingElse = t2.id);
Note that your intended logic leaves open an edge case where A = B exactly. Assuming you want to include this, one way would be to change one of the inequalities to either >= or <=.

You can do it with a CASE expression:
SELECT *
FROM table1
INNER JOIN table2 ON table2.id = CASE
WHEN (A > B) THEN table1.id
WHEN (A < B) THEN table1.somethingElse
END
Note that this query still can use an index on table2(id).
It's also possible to use nested IF() functions:
SELECT *
FROM table1
INNER JOIN table2 ON
table2.id = IF(A > B, table1.id, IF(A < B, table1.somethingElse, NULL))
But that's not very readable.
Also note, that in both queries there will be no match if A = B. But that is what your "pseudo code" suggests.

I'm not sure if I understand what exactly do you need. But probably something like this. It's in PostgreSQL.
SELECT *
FROM
table1
INNER JOIN table2 ON
CASE WHEN table1.A > table2.B THEN table1.id = table2.id
ELSE table1.id = table2.id2
END;

Related

How to LEFT JOIN table1 ON table2 WHERE table2 row fulfills certain conditions

Please consider this query:
SELECT table1.* ,
(SELECT quantity FROM table2 WHERE id = table1.id AND table2.location = 10) quantity,
(SELECT reorder_level FROM table2 WHERE id = table1.id AND table2.location = 10) reorder_level,
(SELECT stock_date FROM table2 WHERE id = table1.id AND table2.location = 10) stock_date
FROM table1
WHERE category_id = 5 ORDER BY table1.id;
The aliases quantity, location and stock_date are obviously referencing a a row in table2 that fulfill the condition: id=table1.id and location=10.
This query works, but is probably suboptimal as a result of the clumsy subqueries.
How can I best join table1 to table2 USING(id) but only on rows where location is also 10.
TIP: One row from table1 has many rows in table2.
Unfortunately, the actual table definitions are much more complex, and I reckoned it might be counter-productive to dump the entire thing on this thread.
You can use additional condition in ON() part so it will join only rows which fulfills the provided criteria
SELECT t1.* ,
t2.quantity ,
t2.reorder_level,
t2.stock_date
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id AND t2.location = 10
WHERE t1.category_id = 5
ORDER BY t1.id;
Another way would be use a subselect for your table2 and select only rows where location is equal to 10
SELECT t1.* ,
t2.quantity ,
t2.reorder_level,
t2.stock_date
FROM table1 t1
LEFT JOIN
(SELECT * FROM table2 WHERE t2.location = 10) t2
ON t1.id = t2.id
WHERE t1.category_id = 5
ORDER BY t1.id;

mysql - conditional 'on clause' in mysql join

I try to establish a conditional 'on clause' in a mysql join.
If field1 is not empty, this should be used in the 'on claus',
but if empty, field2 instead should be used.
SELECT * FROM table1
JOIN table2
IF (field1!='') THEN (
ON table1.field1 = table2.field1
AND table1.field3 = table2.field3
)
ELSE (
ON table1.field2 = table2.field2
AND table1.field3 = table2.field3
)
END IF
Any idea if this is possible on how it could be done?
Edit:
I forgot to explain that both tables contain empty fields and I try to prevent that mysql uses these fields for the join, as that gives a (very) lot of joins, so my idea should be more like this:
SELECT * FROM table1
JOIN table2
IF (table1.field1!='' AND table2.field1!='') THEN (
ON table1.field1 = table2.field1
AND table1.field3 = table2.field3
)
ELSE (
ON table1.field2 = table2.field2
AND table1.field3 = table2.field3
)
END IF
Try this instead:
SELECT * FROM table1 t1
LEFT JOIN table2 t2
LEFT JOIN table2 t3
on t1.Field1=t2.Field1 and t1.Field3=t2.Field3
on t1.Field2=t3.Field2 and t1.Field3=t3.Field3
Then use a condition tho choose the field from table2 or table3.
Hope this helps you.
EDIT
To select the right field use this:
SELECT t1.*, IF(t2.field1 is null, t3.field1, t2.Field1) as Field1
I think you can do something like this:
SELECT * FROM table1
JOIN table2 ON
(
(table1.field1 = '' AND table1.field2 = table2.field2 AND table1.field3 = table2.field3)
OR
(table1.field1 != '' AND table1.field1 = table2.field1 AND table1.field3 = table2.field3)
)
(note: I have no idea how efficient or otherwise this approach is)
You should consider converting your INNER JOIN to a LEFT JOIN as already shown in other answer like
SELECT * FROM table1 t1
LEFT JOIN table2 t2
ON t1.field1 = t2.field1 AND t1.field3 = t2.field3
LEFT JOIN table2 t22
ON t1.field2 = t22.field2 AND t1.field3 = t22.field3
You can as well try something like below
SELECT t1.*
FROM table1 t1
JOIN table2 t2
ON t1.field1 = t2.field1 AND t1.field3 = t2.field3
OR t1.field2 = t2.field2 AND t1.field3 = t2.field3

MySql Inner join based on non empty columns

I have Two tables :
Table1, Table2
I have to write a SQL query which has inner join on three columns based
on <> 0 condition
on these tables.
My condition is
if(table1.ID != 0), then inner join on table1.ID = table2.ID else,
if(table1.MemberID != 0), then inner join on table1.MemberID = table2.MemberID else,
inner join on table1.PersonID = table2.PersonID
You can use a conditional statement (case when for example) in a join clause.
select t1.*, t2.*
from table1 t1
inner join table2 t2 on
(case when
t1.ID != 0
then t1.ID =t2.Id
else
case when t1.MemberId !=0
then t1.MemberId = t2.MemberId
else
t1.PersonId = t2.PersonId
end
end)
see SqlFiddle
This should work.
select *
from Table1, Table2
where table1.Personid = table2.personId
and (((Table1.id != 0) and (Table1.id = table2.Id))
or ((Table1.memberid != 0) and (Table1.memberid = table2.memberId)))

Is is possible to simplify this SQL UNION query?

Is is possible to simplify this UNION to avoid the near redundancy of the queries being unioned? As seen here, both queries are similar. They just join on a different column in table2. The reason i use Union, instead of just Inner Joining 2x in the same query is because the results must be in 1 column by virtue of the fact that this queries is used as a subquery.
SELECT t1.id as id
FROM table1 g
INNER JOIN table2 t1 on g.t_id = t1.id
WHERE g.id=1
UNION
SELECT t2.id as id2
FROM table1 g
INNER JOIN table2 t2 on g.t2_id = t2.id
WHERE g.id=1
I don't see why this couldn't be treated as a simple inner join that can be satisfied by a match in either of two predicates. I've removed the original table aliases of t1, t2, and g for the sake of clarity. Since I don't know if the query could produce duplicate rows, I used DISTINCT in order to collapse duplicate rows in the same manner that the UNION did in the original query.
SELECT DISTINCT table2.id
FROM table1
INNER JOIN table2
ON ( table1.t_id = table2.id OR table1.t2_id = table2.id )
WHERE table1.id = 1
;
It is possible to do with two joins, and the IFNULL() function:
SELECT IFNULL (t1.id, t2.id) as id
FROM table1 g
INNER JOIN table2 t1 on g.t_id = t1.id
INNER JOIN table2 t2 on g.t2_id = t2.id
WHERE g.id=1
You might find this simpler:
select distinct t.id
from table2 t
where t.id in (select g.t_id from table1 g) or
t.id in (select g.t2_id from table1 g)
However, the performance would be awful on MySQL. You can also do:
select distinct t.id
from table2 t
where exists (select 1 from table1 g where g.t_id = t.id or g.t2_id = t.id)
The second version should work better in MySQL.

Proper order syntax for MySQL INNER JOIN ON (Basic Q)

I have the following MySQL query statement:
SELECT *
FROM table1 INNER JOIN table2
ON table1.id = table2.id
WHERE 1
Does it matter if my inner join on statement is table1.id = table2.id vs. table2.id = table1.id?
There is no functional or performance difference between the two options you presented.
It's purely a stylistic choice.
Personally I prefer this style, but I'm sure there are others who do it differently:
SELECT ...
FROM table1
INNER JOIN table2 ON table2.id = table1.id
INNER JOIN table3 ON table3.id = table1.id
WHERE ...