3

我有一个查询来获取两个值:

string query = @"SELECT price, weight
                 FROM   map 
                 WHERE  width = @width AND height = @height LIMIT 1";

if (_connSource.State != ConnectionState.Open)
    _connSource.Open();
MySqlCommand cmd = new MySqlCommand(query, _connSource);
cmd.Parameters.AddWithValue("width", width);
cmd.Parameters.AddWithValue("height", height);
r = cmd.ExecuteReader();

if (!r.Read())
{
    r.Close();

    query = @"SELECT retail_price, 0
              FROM   globe
              WHERE  PK_Id = @PK_Id LIMIT 1"

    cmd = new MySqlCommand(query, _connSource);
    cmd.Parameters.AddWithValue("PK_Id ", 1);
    r = cmd.ExecuteReader();
 }

我需要的是根据一个条件获取price和,但如果它不存在于表中,那么我需要从一个没有约束的全新表中获取另外两个字段和一个常量 0(不管它是什么)从上表。我可以在一个查询中得到这两个吗?weightretail_price

注意:请给我优化的查询,它不会强制多次读取相同的值(此函数在一次操作中执行数千次,因此速度非常关键 - 这是我试图将它整合到一起的原因询问)。谢谢..

4

4 回答 4

3

语法有点难看,但我认为你可以做到:

(SELECT price, weight
 FROM map 
 WHERE width = @width AND height = @height LIMIT 1)
UNION ALL
(SELECT retail_price as price, 0 as weight
 FROM  globe
 WHERE PK_Id = @PK_Id LIMIT 1)

这将返回 0 到 2 行。如果返回 2 行,则选择第 1 行。

编辑您可以尝试通过使用这个可怕的构造来避免第二次查询的成本。我不确定 MySQL 是否能很好地处理它,但它很有可能避免第二个查询:

select
    ifnull(price, (select retail_price from globe where PK_Id = @PK_Id LIMIT 1))
,   ifnull(weight, 0)
from map 
WHERE width = @width AND height = @height LIMIT 1
于 2012-04-17T14:22:16.647 回答
1

如果地图 WHERE 没有 Resultrow,则 DBNull 将被替换为地球值

SELECT 
    price = IFNULL(map.price,gl.price), 
    weight = IFNULL(map.weight,0)
FROM   map 
LEFT JOIN globe gl ON PK_Id = @PK_Id    
WHERE  width = @width AND height = @height 
LIMIT 1
于 2012-04-17T14:36:57.010 回答
1

我确实得到了一个非常hacky的解决方案,不小心。以下是如何做到这一点:

SELECT price, weight
FROM map
WHERE width = @width AND height = @height LIMIT 1

UNION ALL

SELECT retail_price, 0
FROM  globe
WHERE PK_Id = @PK_Id LIMIT 1

如果我在第一个选择本身中得到答案,该LIMIT 1子句实际上会限制它读取第二个值。请注意,我没有在任何地方添加括号,因此 MySQL 不会将其视为正常 UNION ALL在此处此处阅读更多相关信息

显然,您可以这样做以使其更有意义,但我认为它的性能不会更好:

SELECT price, weight
FROM map
WHERE width = @width AND height = @height LIMIT 1

UNION ALL

(SELECT retail_price, 0
FROM  globe
WHERE PK_Id = @PK_Id LIMIT 1) LIMIT 1

在这里,由于我添加了括号,它就像普通的 UNION ALL 一样工作,也就是说,如果可能,我应该获取两条记录,但是LIMIT 1查询末尾的最后一个子句将结果限制为第一组。

于 2012-04-18T14:38:44.370 回答
0

由于您的“限制”子句保证每个查询最多一行,您可以使用左连接,并使用“IF()”处理“地图”记录的存在:

select ifnull(m.price,g.price), ifnull(m.weight,g.weight) from
(SELECT retail_price as price, 0 as weight
 FROM  globe
 WHERE PK_Id = @PK_Id LIMIT 1) g
LEFT JOIN
(SELECT price, weight
 FROM   map 
 WHERE  width = @width AND height = @height LIMIT 1) m
ON 1=1

上述查询假定映射表中的价格和重量不能为空。

于 2012-04-17T14:35:40.003 回答