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
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;
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
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 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.
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 ...