> An apple farmer has several farms and at them, numbered boxes to hold
> the fruit. The boxes can be numbered 1-99. The farmer has two
[quoted text clipped - 50 lines]
> table so that the box_weight table as a forth column indicating the
> fruit type?
Have a look at OUTER JOINs.

Signature
Knut Stolze
DB2 z/OS Utilities Development
IBM Germany
Tonkuma - 16 Aug 2007 18:56 GMT
I think Greg's essential question is how to realize the requirement
which is
"every box that is not listed(in box_fruit) for some other fruit is
assumed to be for apple(i.e. BOX 0)".
Note: the phrases in parentheses are added by me.
If so, following may be an answer.
------------------------- Commands Entered -------------------------
SELECT F.FARM, F.BOX
, CASE F.BOX WHEN 0 THEN 'apple' ELSE FRUIT END AS fruit
, COALESCE(WEIGHT,0) AS weight
FROM box_fruit F
LEFT OUTER JOIN
LATERAL
(SELECT SUM(WEIGHT)
FROM box_weight W
WHERE F.FARM = W.FARM
AND
( F.BOX = W.BOX
OR
F.BOX = 0
AND
NOT EXISTS
(SELECT *
FROM box_fruit FNE
WHERE FNE.FARM = W.FARM
AND FNE.BOX = W.BOX
)
)
) W(WEIGHT)
ON 0=0
;
--------------------------------------------------------------------
FARM BOX FRUIT WEIGHT
----------- ----------- --------------- -----------
1 0 apple 72
1 59 pear 14
1 60 pear 0
1 91 plum 10
1 92 plum 0
1 96 pear 17
2 0 apple 26
2 60 pear 0
2 71 plum 0
2 91 plum 0
2 98 pear 0
3 0 apple 14
3 1 plum 17
3 2 plum 13
3 96 pear 0
15 record(s) selected.
Greg - 16 Aug 2007 21:08 GMT
I'm looking for the query that will produce the following result:
FARM BOX WEIGHT FRUIT
1 1 13 apple (because the box 1 fruit was not
explicitly listed and the default fruit (box 0) is apple)
1 2 12 apple "
1 3 13 apple "
1 59 14 pear (because box 59 was explicitly
listed as pear)
1 65 15 apple
1 91 10 plum
1 96 17 pear
1 99 19 apple
2 1 12 apple
2 2 14 apple
3 1 17 plum
3 2 13 plum
3 3 14 apple
Tonkuma - 16 Aug 2007 21:41 GMT
It is a most basic and simple LEFT OUTER JOIN, if you know the builtin
function COALESCE.
------------------------- Commands Entered -------------------------
SELECT W.FARM, W.BOX, WEIGHT
, COALESCE(FRUIT, 'apple') AS FRUIT
FROM box_weight W
LEFT OUTER JOIN
box_fruit F
ON F.FARM = W.FARM
AND F.BOX = W.BOX
ORDER BY
W.FARM, W.BOX;
--------------------------------------------------------------------
FARM BOX WEIGHT FRUIT
----------- ----------- ----------- ---------------
1 1 13 apple
1 2 12 apple
1 3 13 apple
1 59 14 pear
1 65 15 apple
1 91 10 plum
1 96 17 pear
1 99 19 apple
2 1 12 apple
2 2 14 apple
3 1 17 plum
3 2 13 plum
3 3 14 apple
13 record(s) selected.
Greg - 17 Aug 2007 15:33 GMT
Thank you so much for your help so far.
What if the box 0 fruit for a particular farm is not apple?
BOX-FRUIT TABLE:
FARM BOX FRUIT
1 0 apple
1 59 pear
1 60 pear
1 91 plum
1 92 plum
1 96 pear
2 0 apple
2 60 pear
2 71 plum
2 91 plum
2 98 pear
3 0 pear <=====
3 1 plum
3 2 plum
3 96 apple
same box-wieght table
RESULT:
FARM BOX WEIGHT FRUIT
----------- ----------- ----------- ---------------
1 1 13 apple
1 2 12 apple
1 3 13 apple
1 59 14 pear
1 65 15 apple
1 91 10 plum
1 96 17 pear
1 99 19 apple
2 1 12 apple
2 2 14 apple
3 1 17 plum
3 2 13 plum
3 3 14 pear (not apple since box0
fruit is pear for this farm)
COALESCE(FRUIT, 'apple') would have to change to the equivalent of
COALESCE(FRUIT, {whatever box0 fruit is for this farm})
Greg
>> The question is, how do I join the fruit boxes table to the box weight table so that the box weight table as a forth column indicating the fruit type? <<
This design flaw is common enough to have a name --Attribute
Splitting. What are the attributes of a fruit box? Are they all in
one table or are they split across two or more tables (so you have to
do complex joins for the most basic facts)? You already know the
answer to that one!
Try a relational design, with constraints, etc. Why did you use
singular names for tables which model sets of things? Your fruits
seem to be labeled with the type and the variety of the produce, so
let's code that as two columns.
CREATE TABLE FruitBoxes
(farm_nbr INTEGER NOT NULL,
box_nbr INTEGER NOT NULL
CHECK (box_nbr BETWEEN 1 AND 99),
PRIMARY KEY (farm_nbr, box_nbr),
box_wgt INTEGER DEFAULT 0 NOT NULL
CHECK (box_wgt >= 0),
fruit_type CHAR(5) DEFAULT 'Apple' NOT NULL,
fruit_variety CHAR(10) DEFAULT '{{unk}}' NOT NULL,
FOREIGN KEY (fruit_type, fruit_variety)
REFERENCES Fruits (fruit_type, fruit_variety)
..);
CREATE TABLE Fruits
(fruit_type CHAR() NOT NULL,
fruit_variety CHAR(10) NOT NULL,
PRIMARY KEY (fruit_type, fruit_variety),
..);
INSERT INTO Fruits
VALUES ('Apple', 'Macintosh', ..),
('Apple', 'Golden_Del', ..),
('Apple', 'Red_Del', ..),
('Apple', '{{unk}}', ..), -- unknown generic apple code
('Pear', 'Bartlett', ..), ..;
Now let's assure that all the boxes are inventoried with an
assertion.
CREATE ASSERTION AllBoxesInventoried
AS
CHECK (99 = ALL (SELECT COUNT(*)
FROM FruitBoxes
GROUP BY farm_nbr));
If you are worried about the extra storage that a proper design
requires, consider that you can get megabytes for pennies, but the
execution time you will waste, the complexity of maintaining lateral
outer joins, lack of data integrity, etc. in what you have now will
cost you dollars in human time and errors.