JohnDubya
05-14-2009, 11:10 PM
Ugh. Once again, I've gotten stumped on a complex query. I'll try to make it as simple as possible. Basically, we have a DB of people's information, and we allow for our clients to add custom categories to be able to add additional fields themselves. So for each custom category, there are multiple options to choose from. And each person can be associated with one of these options under each custom_field. Here is the DB structure:
TABLES
`custom_fields` => (field_id, name) [this table isn't used in the query, but here to show DB structure]
`custom_options` => (option_id, field_id, value)
`custom_attributes` => (option_id, person_id)
`person` => (person_id, name)
PROBLEM
I need to filter on these things:
custom_options.field_id = 4
custom_options.option_id = custom_attributes.option_id
custom_attributes.person_id = p.person_id
And in addition to needing to filter on these things, I also need the query to show people who do NOT have an option entry in `custom_attributes` for field_id = 4. So it would basically need to return NULL in that case but still show the record. Here's what I've got so far:
$query = "SELECT cuo1.value value FROM ( (person p)
LEFT JOIN custom_attributes cua1 ON cua1.person_id = p.person_id
LEFT JOIN custom_options cuo1 ON cuo1.option_id = cua1.option_id )
WHERE ( (cuo1.field_id = 4 OR cuo1.field_id IS NULL) OR
(NOT EXISTS (SELECT 1 FROM custom_attributes tcua1
JOIN custom_options tcuo1 ON tcuo1.field_id = 4
WHERE tcua1.person_id = p.person_id AND tcua1.option_id = tcuo1.option_id)) )
GROUP BY p.person_id ORDER BY p.name";
This query correctly returns 14 rows, but the value is not completely correct. It returns the correct option value for people who only have a `custom_person` entry for an option under field_id = 4, but if they have additional `custom_person` entries, one of them is sometimes returned too.
So how do I get this query to ONLY grab the option's value for a field_id = 4? Thanks for any help you can provide!
TABLES
`custom_fields` => (field_id, name) [this table isn't used in the query, but here to show DB structure]
`custom_options` => (option_id, field_id, value)
`custom_attributes` => (option_id, person_id)
`person` => (person_id, name)
PROBLEM
I need to filter on these things:
custom_options.field_id = 4
custom_options.option_id = custom_attributes.option_id
custom_attributes.person_id = p.person_id
And in addition to needing to filter on these things, I also need the query to show people who do NOT have an option entry in `custom_attributes` for field_id = 4. So it would basically need to return NULL in that case but still show the record. Here's what I've got so far:
$query = "SELECT cuo1.value value FROM ( (person p)
LEFT JOIN custom_attributes cua1 ON cua1.person_id = p.person_id
LEFT JOIN custom_options cuo1 ON cuo1.option_id = cua1.option_id )
WHERE ( (cuo1.field_id = 4 OR cuo1.field_id IS NULL) OR
(NOT EXISTS (SELECT 1 FROM custom_attributes tcua1
JOIN custom_options tcuo1 ON tcuo1.field_id = 4
WHERE tcua1.person_id = p.person_id AND tcua1.option_id = tcuo1.option_id)) )
GROUP BY p.person_id ORDER BY p.name";
This query correctly returns 14 rows, but the value is not completely correct. It returns the correct option value for people who only have a `custom_person` entry for an option under field_id = 4, but if they have additional `custom_person` entries, one of them is sometimes returned too.
So how do I get this query to ONLY grab the option's value for a field_id = 4? Thanks for any help you can provide!