views:

56

answers:

3

First off, here's my SQL query:

SELECT research_cost, tech_name,
    (SELECT research_cost
        FROM technologies
        WHERE research_cost <= USERS_RESEARCH_POINTS_VALUE
        ORDER BY research_cost DESC
        LIMIT 1) as research_prev,
    (SELECT cost
        FROM technology_costs
        WHERE id = 18
        LIMIT 1) as technology_cost
FROM `technologies`
    JOIN technology_costs
    ON id = COUNT_OF_TECHS_USER_LEARNED
WHERE research_cost > USERS_RESEARCH_POINTS_VALUE
ORDER BY research_cost ASC
LIMIT 1

Website link: http://www.joemajewski.com/fortress/

Some people might consider the above query to be moderate-sized, or even small; not me. For me, that's one of the largest and most complex SQL queries I've ever written, so I pushed myself to my limits.

Anyways, the query itself has no syntax errors, and it does exactly what I want it to do, for the most part. There's one minor issue, however.

If the main SELECT clause doesn't return a row (the "SELECT research_cost, tech_name FROM technologies WHERE research_cost > whatever"), then the entire query is an empty set.

If it helps, Fortress is this game that I'm working on. It's a browser-based MMORPG where users build an army to try and get a top stop in the leaderboards. Technologies are a game mechanic where users purchase upgrades to their stats (gold income, unit production, etc). Researching is a game mechanic that allows you to learn new technologies by training scientists to do the researching. That's what this query is all about. It grabs the current technology that is being researched, as well as the research cost of it. It additionally grabs the cost in gold of how much the next technology will cost.

So... is there any way that I can force at least a null row to be returned in the result set, as the nested select statements retrieve variables that I need in the script, even if the outer query returns nothing. Or could someone possibly change it around so that a result is always returned.

If anything else is needed, let me know. :)

A: 

I would try wrapping it in ISNULL()

Like this:

SELECT research_cost, tech_name, 
ISNULL((SELECT research_cost 
    FROM technologies 
    WHERE research_cost <= USERS_RESEARCH_POINTS_VALUE 
    ORDER BY research_cost DESC 
    LIMIT 1), 0.00) as research_prev, 
    [the rest of your query here]

//Note: instead of '0.00' you'll want some appropriate default value.
AllenG
I think you misunderstood. It's not the inner queries that are coming back without results, it's the main query.
Fosco
@Fosco - You're right. I did misread. I'll leave this here for a few minutes (to document my shame) and then delete.
AllenG
@Fosco: Yeah, that's correct. Anyways, I've never heard of the ISNULL() function before, so thanks for the tip. I think the syntax that I was using may have been incorrect because I tested it out and it failed.
Joe Majewski
Hi Joe.. how about throwing a closed beta promo code my way? [email protected]
Fosco
A: 

You can try getting an empty row with the proper schema first, then try filling those rows in with the query you wrote above. The only downside is the additional query to do so.

That way, if your query above returns nothing, you still have the empty row and you can check on that.

Duracell
The reason I'm doing it this way in the first place is to reduce the amount of queries. I could have one extra simply query and the problem would be solved, but I'm optimizing at the moment. Thanks for the suggestion though.
Joe Majewski
+2  A: 

This query always returns at least 1 row

SELECT * FROM (__your old query__)aaa
UNION 
SELECT NULL as research_cost, NULL as tech_name, NULL as research_prev, 
... etc [FROM DUAL] // DUAL is a  dummy table in mysql
a1ex07
Can you explain how this works exactly. I've never used union before so this is all new syntax for me.
Joe Majewski
Your original query remains untouched, `SELECT * FROM (your_query)aaa` is used just to make sure your limit and ordery by clause applied. Then we union this result with `SELECT NULL, NULL, ...` This query doesn't have `FROM` clause, and it always returns exactly one row (NULL,NULL,NULL, etc). As far as I understood your question it will work for you. All you need in client-side is to ignore the record with all fields equal NULL.
a1ex07
You should maybe show the FROM clause for the second query...unless MySQL is like SQL Server and you don't always need one.
Patrick Marchand
added `FROM DUAL`
a1ex07
Weird, that "FROM DUAL" thing. I get no error with this new query, but no result set either. Doesn't even say "empty set".
Joe Majewski
Using phpMyAdmin, that is.
Joe Majewski