It can be done using some multiple joins from table1 into table2 and then use those joins combined with case/calculation logic, or using sub-selects.
But it seems rather complex to want to do that in a single query/single join - that I'd recommend finding an alternative way to do it. It's something which is a good candidate to solve in application logic.
However, I think the route you want to go is something like this:
SELECT
T1.*,
CASE
WHEN T2.value = '1' THEN 'CalculateStuffBasedOnT3OrT4'
WHEN T2.value = '2' THEN
CASE
WHEN t3.value IS NULL THEN 'CalculateOtherStuffBasedOnT3OrT4'
WHEN T3.value = '2' THEN 'CalculateMoreStuffBasedOnT3OrT4'
ELSE 'SomethingElse'
END
ELSE 'Something'
END
FROM tbl1 T1
LEFT JOIN tbl2 T2 ON T1.id = T2.id AND T2.key = 'm_type'
LEFT JOIN tbl2 T3 ON T1.id = T3.id AND T3.key = 'm_routine'
LEFT JOIN tbl2 T4 ON T1.id = T4.id AND T4.key = 'm_date'
Such a query can then be used as foundation in a subquery to select the posts you want.
But this will quickly become quite complex and unmaintainable.
So I'd advice you to rethink the strategy and go with designing the query dynamically in you php code, or rethink the data structure, or utilize multiple queries to solve it.
- You can't have anything about the inner tables in the
WHERE
clause for the outer joins to work as expected - move those to JOIN
conditions
- You would need
FULL JOIN
which is something that MySQL sadly doesn't support - you can emulate FULL JOIN
with two outer joins and UNION
SELECT
a.`cust`
,a.`type`
,IF(a.`data1`=b.`data1`,a.`data1`,CONCAT("<< ",a.`data1`," >>")) AS 'data1'
,IF(a.`data2`=b.`data2`,a.`data2`,CONCAT("<< ",a.`data2`," >>")) AS 'data2'
,a.`data2`,
IF(a.`data1`=b.`data1` AND a.`data2`=b.`data2`,'MATCH','NO MATCH') AS Matched
,b.`cust`
,b.`type`
,IF(b.`data1`=a.`data1`,b.`data1`,CONCAT("<< ",b.`data1`," >>")) AS 'data1'
,IF(b.`data2`=a.`data2`,b.`data2`,CONCAT("<< ",b.`data2`," >>")) AS 'data2'
FROM `test`.`tab1` a
LEFT OUTER JOIN `test`.`tab1` b ON (a.`type`=b.`type`) AND (a.`data1`=b.`data1` OR a.`data2`=b.`data2`) AND b.`cust` = 200
WHERE 1=1 AND a.`cust` = 100
UNION
SELECT
a.`cust`
,a.`type`
,IF(a.`data1`=b.`data1`,a.`data1`,CONCAT("<< ",a.`data1`," >>")) AS 'data1'
,IF(a.`data2`=b.`data2`,a.`data2`,CONCAT("<< ",a.`data2`," >>")) AS 'data2'
,a.`data2`,
IF(a.`data1`=b.`data1` AND a.`data2`=b.`data2`,'MATCH','NO MATCH') AS Matched
,b.`cust`
,b.`type`
,IF(b.`data1`=a.`data1`,b.`data1`,CONCAT("<< ",b.`data1`," >>")) AS 'data1'
,IF(b.`data2`=a.`data2`,b.`data2`,CONCAT("<< ",b.`data2`," >>")) AS 'data2'
FROM `test`.`tab1` a
RIGHT OUTER JOIN `test`.`tab1` b ON (a.`type`=b.`type`) AND (a.`data1`=b.`data1` OR a.`data2`=b.`data2`) AND a.`cust` = 100
WHERE 1=1
AND b.`cust` = 200;
Best Answer
The idea of next or previous rows makes sense only in the presence of explicitly specified
ORDER BY
clause.Now assuming that you need your resultset ordered by
date
you can achieve your goal either by using a subqueryor by leveraging user(session) variables
Sample output (in both cases):
Here is SQLFiddle demo