【问题标题】:Help Me with my SQL Query (Need it to always return at least one row.)帮助我处理我的 SQL 查询(需要它始终返回至少一行。)
【发布时间】:2011-03-25 22:33:08
【问题描述】:

首先,这是我的 SQL 查询:

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

网站链接:http://www.joemajewski.com/fortress/

有些人可能认为上面的查询是中等大小,甚至很小;不是我。对我来说,这是我写过的最大、最复杂的 SQL 查询之一,所以我把自己逼到了极限。

无论如何,查询本身没有语法错误,而且大部分情况下它完全符合我的要求。但是,还有一个小问题。

如果SELECT 主子句没有返回一行(“SELECT research_cost, tech_name FROM technologies WHERE research_cost > 不管”),那么整个查询是一个空集。

如果有帮助的话,Fortress 就是我正在开发的这款游戏。这是一款基于浏览器的 MMORPG,用户可以在其中组建一支军队,试图在排行榜中名列前茅。技术是一种游戏机制,用户可以在其中购买升级到他们的统计数据(黄金收入、单位产量等)。研究是一种游戏机制,可让您通过培训科学家进行研究来学习新技术。这就是这个查询的全部内容。它抓住了当前正在研究的技术,以及它的研究成本。它还计算了下一项技术的成本。

所以...有什么方法可以强制在结果集中至少返回一个空行,因为嵌套的 select 语句会检索我在脚本中需要的变量,即使外部查询什么也不返回。或者有人可能会改变它,以便始终返回结果。

如果还需要什么,请告诉我。 :)

【问题讨论】:

  • “默认”行应该返回什么?
  • 您是否尝试过 INNER JOIN 而不是 JOIN?只是一个想法......
  • @Benny.. join = 内连接。这是暗示的。
  • 我正在尝试了解您要从数据库中检索的内容。看起来你想要用户已经拥有的最昂贵的技术,以及该技术的成本,以及用户没有的最便宜的技术,以及它的成本。这就是你要找的吗?
  • @Joe,如果您开始使用表别名,那就太好了。我想知道技术和技术成本之间的联系以及哪些领域来自哪里。我喜欢下面的 UNION 查询答案,但我打算用 CASE 语句编写一个大型查询。

标签: sql mysql optimization query-optimization resultset


【解决方案1】:

我会尝试将它包装在 ISNULL() 中

像这样:

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.

【讨论】:

  • 我想你误会了。没有结果返回的不是内部查询,而是主要查询。
  • @Fosco - 你是对的。我确实看错了。我将把它留在这里几分钟(以记录我的耻辱)然后删除。
  • @Fosco:是的,没错。无论如何,我以前从未听说过 ISNULL() 函数,所以感谢您的提示。我认为我使用的语法可能不正确,因为我对其进行了测试但失败了。
  • 嗨,乔.. 以我的方式抛出封闭测试版促销代码怎么样? gfosco@gmail.com
【解决方案2】:

您可以先尝试使用正确的架构获取一个空行,然后尝试使用您在上面编写的查询填充这些行。唯一的缺点是这样做需要额外的查询。

这样,如果您上面的查询没有返回任何内容,您仍然有空行,您可以检查它。

【讨论】:

  • 我这样做的原因首先是为了减少查询量。我可以有一个额外的简单查询,问题就会得到解决,但我目前正在优化。不过感谢您的建议。
【解决方案3】:

此查询始终返回至少 1 行

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

【讨论】:

  • 你能解释一下它是如何工作的吗?我以前从未使用过 union,所以这对我来说是全新的语法。
  • 您的原始查询保持不变,SELECT * FROM (your_query)aaa 仅用于确保应用您的 limit 和 ordery by 子句。然后我们将这个结果与SELECT NULL, NULL, ... 联合起来。这个查询没有FROM 子句,它总是只返回一行(NULL、NULL、NULL 等)。据我了解你的问题,它会为你工作。在客户端,您只需要忽略所有字段都为 NULL 的记录。
  • 您可能应该为第二个查询显示 FROM 子句...除非 MySQL 类似于 SQL Server 并且您并不总是需要它。
  • 很奇怪,那个“来自双重”的东西。我对这个新查询没有任何错误,但也没有结果集。甚至没有说“空集”。
【解决方案4】:

一种不需要第二次选择列出每个原始列的方法:

SELECT yourstuff.*
FROM (__your original query__) yourstuff
RIGHT OUTER JOIN (SELECT 1 AS fake FROM DUAL) faketable ON 1=1;

如果您的原始查询返回任何行,它们将不受影响地通过。如果它不返回任何行,您将获得所有空值的一行。

【讨论】:

    猜你喜欢
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    相关资源
    最近更新 更多