Thread: Design and Question

Design and Question

From
PostgreSQL Admin
Date:
Hi,

I have BOTH a sql AND db design question.

I'm creating a cookbook DB with have broken the table into this:

RECIPE TABLE

Column | Type | Modifiers
-------------------+--------------------------+------------------------------------------------------
id | integer | not null default nextval('recipes_id_seq'::regclass)
title | character varying(150) | not null
description | text | not null
servings | integer |
instruction | text | not null
photo | character varying(100) | not null
difficulty | integer |
cuisine | smallint |
course | smallint |
season | smallint |
dietary | smallint |
technique | smallint |
published_date | timestamp with time zone | not null
publishing_rights | boolean | not null
credits | character varying(100) | not null
approved | boolean | default false
cooktime | integer |
preptime | integer |

and this:

RECIPE DIET INFO TABLE
Column | Type | Modifiers
-----------+----------------------+-----------------------------------------------------------
id | integer | not null default nextval('recipes_diet_id_seq'::regclass)
recipe_id | integer | not null
diet | character varying(1) |

RECIPE SEASON TABLE
Column | Type | Modifiers
-----------+----------------------+-------------------------------------------------------------
id | integer | not null default nextval('recipes_season_id_seq'::regclass)
recipe_id | integer | not null
season | character varying(1) |

I can perform is query ->

select title from recipes where id in (select recipe_id from 
recipes_season where season in ('P', 'W'));

title
---------------------------------------
ButterFlied Chicken Fillets with Lime
Balsamic Vinegar Chicken with Beans

(2 rows)

select title from recipes where id in (select recipe_id from 
recipes_diet where diet in ('P'));

title
---------------------------------------
ButterFlied Chicken Fillets with Lime

How do I combine the two in a query?


Re: Design and Question

From
Niklas Johansson
Date:
On 10 jul 2008, at 14.50, PostgreSQL Admin wrote:
> How do I combine the two in a query?

If you're looking for recipes that match *either* criterion (season  
*or* diet), you could add the two subqueries generating the ids using  
UNION or UNION ALL:

SELECT title FROM recipes WHERE id IN (
SELECT recipe_id FROM recipes_season WHERE season IN ('P', 'W')
UNION [ALL]
SELECT recipe_id FROM recipes_diet WHERE diet IN ('P')
);

or, you could use joins:

SELECT title FROM recipes r
LEFT JOIN recipes_season rs ON r.id=rs.recipe_id
LEFT JOIN recipes_diet rd ON r.id=rd.recipe_id
WHERE rs.season IN ('P', 'W') OR rd.diet IN ('P');


If, on the other hand, you're looking for recipes that match *both*  
criteria, use:

SELECT title FROM recipes WHERE id IN (SELECT recipe_id FROM  
recipes_season WHERE season IN ('P', 'W'))
AND id IN (SELECT recipe_id FROM recipes_diet WHERE diet IN ('P'));

or:

SELECT title FROM recipes r
INNER JOIN recipes_season rs ON r.id=rs.recipe_id
INNER JOIN recipes_diet rd ON r.id=rd.recipe_id
WHERE rs.season IN ('P', 'W') AND rd.diet IN ('P');


The optimal execution plan will be dependent on the size and  
distribution of your data, so you should test the queries with real  
data.



Sincerely,

Niklas Johansson