Reputation: 39
I need an example of a stored procedure that uses the results of two another stored procedures (or even just one) where the results are used as tables in the combining stored procedure. I could likely take it from there.
examples on web (multiple sites) and details at php.net are too simplistic.
The basic issue can be seen here:
SELECT ttd.person_id, weight, min(test_date)
FROM (
CALL get_team_member_body_stats(1) AS tbs,
CALL get_team_member_first_last_test_date(1) AS ttd
WHERE tbs.person_id = ttd.person_id
AND (tbs.test_date = ttd.first_test OR tbs.test_date = ttd.last_test)
GROUP BY ttd.person_id;
END
Thanks for any help. I've beat my head against this for several hours yesterday and today in online searching and experimenting.
Details:
stored procedure get_team_member_body_stats(IN team_id INT) works over 5 tables (person, team, person_team, body_stats, person_body_stats) and produces:
person_id | body_stats_id | weight | test_date |
2 2 200 2011-01-01
4 3 250 2011-01-01
1 5 145 2011-03-01
2 6 210.4 2011-03-01
5 7 290 2011-03-01
1 8 140 2011-04-01
1 9 135 2011-05-01
4 11 245 2011-05-01
stored procedure get_team_member_first_last_test_date(IN team_id INT) works over the same tables and produces:
person_id | first_test | last_test
1 2011-03-01 2011-05-01
2 2011-01-01 2011-03-01
4 2011-01-01 2011-05-01
5 2011-03-01 2011-03-01
Goal is to join these and produce:
person_id | first_weight | last_weight
1 145 135
2 200 210.4
4 250 245
5 290 290
Thanks
Upvotes: 2
Views: 3529
Reputation: 39
It appears (per this community and because I couldn't find any examples of stored procedures using result sets from other stored procedures as tables in new select tables) that mysql either doesn't support this or that it is ridiculously hard to do what I hoped to do.
So rather than calling stored procedures I copied the queries into this final procedure.
DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `get_team_stats_change`( IN team_id INT ) BEGIN SELECT SUM(start_weight) AS start_weight, SUM(start_body_fat) AS start_body_fat, SUM(current_weight) AS current_weight, SUM(current_body_fat) AS current_body_fat, SUM(weight_change) AS weight_change, SUM(body_fat_change) AS body_fat_change FROM ( SELECT ls.person_id, fs.weight AS start_weight, fs.body_fat AS start_body_fat, ls.weight AS current_weight, ls.body_fat AS current_body_fat, fs.weight - ls.weight AS weight_change, fs.body_fat - ls.body_fat AS body_fat_change FROM (SELECT ttd.person_id, bs.weight, bs.body_fat, bs.test_date FROM body_stats AS bs JOIN ((SELECT pbs.person_id, min(bs.test_date) AS first_test, max(bs.test_date) AS last_test FROM body_stats AS bs, person_body_stats AS pbs, team_member AS tm, team AS t WHERE t.team_id = team_id AND tm.team_id = t.team_id AND tm.person_id = pbs.person_id AND pbs.body_stats_id = bs.body_stats_id AND tm.start_date bs.test_date AND bs.test_date >= t.starting_date GROUP BY person_id) AS ttd, person_body_stats AS pbs) ON bs.test_date = ttd.first_test AND pbs.person_id = ttd.person_id AND pbs.body_stats_id = bs.body_stats_id) AS fs, (SELECT ttd.person_id, bs.weight, bs.body_fat, bs.test_date FROM body_stats AS bs JOIN ((SELECT pbs.person_id, min(bs.test_date) AS first_test, max(bs.test_date) AS last_test FROM body_stats AS bs, person_body_stats AS pbs, team_member AS tm, team AS t WHERE t.team_id = team_id AND tm.team_id = t.team_id AND tm.person_id = pbs.person_id AND pbs.body_stats_id = bs.body_stats_id AND tm.start_date bs.test_date AND bs.test_date >= t.starting_date GROUP BY person_id) AS ttd, person_body_stats AS pbs) ON bs.test_date = ttd.last_test AND pbs.person_id = ttd.person_id AND pbs.body_stats_id = bs.body_stats_id) AS ls WHERE ls.person_id = fs.person_id ) AS delta; END
Upvotes: 1
Reputation: 58441
I don't know how easily you can get these results from 5 tables incorporated into a temporary table or a view but essentially, following should do the same as what you are currently trying to using 3 stored procedures for.
SELECT person_id
, (SELECT weight
FROM FiveTablesResult
WHERE person_id = ftr.person_id
AND test_date = (SELECT MIN(test_date)
FROM FiveTablesResult
WHERE person_id = ftr.person_id)
) AS first_weight
, (SELECT weight
FROM FiveTablesResult
WHERE person_id = ftr.person_id
AND test_date = (SELECT MAX(test_date)
FROM FiveTablesResult
WHERE person_id = ftr.person_id)
) AS last_weight
FROM FiveTablesResult ftr
Note that there is room for optimization but let us first get the correct results returned
Upvotes: 0