views:

33

answers:

2

On the project I am working on, I am stuck with the table structure from Hades. Two things to keep in mind:

  1. I can't change the table structure right now. I'm stuck with it for the time being.
  2. The queries are dynamically generated and not hard coded. So, while I am asking for a query that can pull this data, what I am really working toward is an algorithm that will generate the query I need.

Hopefully, I can explain the problem without making your eyes glaze over and your brain implode.

We have an instance table that looks (simplified) along these lines:

Instances
InstanceID    active
1              Y
2              Y
3              Y
4              N
5              Y
6              Y

Then, there are multiple data tables along these lines:

Table1

InstanceID    field1   reference_field2
1             John      5
2             Sally        NULL
3             Fred          6
4             Joe          NULL


Table2
InstanceID    field3 
5              1
6              1


Table3
InstanceID    fieldID    field4
5               1        Howard
5               2        James
6               2        Betty

Please note that reference_field2 in Table1 contains a reference to another instance. Field3 in Table2 is a bit more complicated. It contains a fieldID for Table 3.

What I need is a query that will get me a list as follows:

InstanceID    field1     field4     
1              John      Howard
2              Sally
3              Fred

The problem is, in the query I currently have, I do not get Fred because there is no entry in Table3 for fieldID 1 and InstanceID 6. So, the very best list I have been able to get thus far is

InstanceID    field1     field4     
1              John      Howard
2              Sally

In essence, if there is an entry in Table1 for Field 2, and there is not an entry in Table 3 that has the instanceID contained in field2 and the field ID contained in field3, I don't get the data from field1.

I have looked at joins till I'm blue in the face, and I can't see a way to handle the case when table3 has no entry.

+2  A: 

LEFT JOIN...

SELECT a.InstanceID, b.field1, d.field4
FROM instances AS a 
    JOIN Table1 AS b ON a.InstanceID = b.InstanceID
    LEFT JOIN Table2 AS c ON b.reference_field2 = c.InstanceID
    LEFT JOIN Table3 AS d ON (c.InstanceID = d.InstanceID AND c.field3 = d.fieldId)
WHERE a.active = 'Y'

The two left joins should handle the case where there are no other rows...

ircmaxell
Your query has one problem. I need to require that the fieldID in Table 3 be the same as the FieldID listed for the instance in Table 2. And, it's that WHERE clause that seems to kill off Fred in my results.
Amy
First, the join does require that the fieldID in table 3 be the same as the one in Table 2 (That's the 2nd part of the ON clause for the table3 join). If the WHERE clause is killing off Fred (which based on your sample data it should not be), then perhaps `active` for fred is really "Y " (with a space)? or something that's not just a plain 'Y'...?
ircmaxell
I think I am starting to see a path to my solution based on what you posted. I need to drop the Where clause and use join syntax instead. The actual query is much nastier than this example, but I think I do see a glimmer of an inkling on how to do it now Thank you.Amy
Amy
Well, I'm glad to help. One word of warning. Don't put where clause conditions in the join clauses (and vise versa). It may prevent MySQL's optimizers from figuring out a proper execution plan (As well as reduce readability significantly, although that may be a problem anyway ;-).
ircmaxell
+1  A: 

It would help if you posted the query you have, because I think you have some mistakes in the table descriptions here, so it's not very clear how are the tables connected.

Anyway, you probably have an inner join in your query (normally written as just JOIN). Replace it with a left outer join (LEFT JOIN). It will not require the right table to contain the row and return NULL instead of the actual value.

Lukáš Lalinský
The closest I can get to the actual query is SELECT Instances.InstanceID,Table1.field1,Table3.field4 FROM Instances LEFT JOIN Table1 ON Instances.InstanceID = Table1.InstanceID LEFT JOIN Table2 ON Instances.InstanceID = Table1.fieldID2 LEFT JOIN Table3 ON Table2.InstanceID = Table3.InstanceID WHERE Instances.active = 'Y' AND (Table3.fieldID = Table2.fieldID OR Table1.field2 IS NULL) ORDER BY Table1.field1 ascThe actual query is more cryptic because the table names are all generated dynamically.
Amy
Well, it's hard to help without seeing the exact tables. For example, here you join the tables on "Instances.InstanceID = Table1.fieldID2". That makes no sense to me, and it's different from what you have written in the question.
Lukáš Lalinský