Like this (with some names changed to protect the not so innocent).
Note that I am actually caching many records per city/state, because I am also looking at category names
By the by, there's no primary key on the CacheCounts table. There is a compound key on (state,city).
CREATE PROCEDURE getCityStateCounts(
DECLARE _found INT;
SELECT COUNT(*) INTO _found
WHERE state = _state AND city = _city;
IF _found = 0 THEN
INSERT INTO CacheCounts( state, city, category, ccount )
SELECT _state AS thestate, _city AS thecity, category, COUNT(*)
FROM ...joined tables not shown...
GROUP BY thestate, thecity, category;
SELECT category, ccount
WHERE state = _state AND city = _city
ORDER BY ccount DESC;