3

2 つの値を取得するクエリがあります。

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();
 }

条件に従って と を取得する必要がありますが、それがテーブルに存在しない場合は、制約のないまったく新しいテーブルからさらに 2 つのフィールドpriceと定数0 (それが何であるかは関係ありません)を取得する必要があります前の表から。1 回のクエリで 2 つを取得できますか?weightretail_price

注:同じ値を複数回読み取ることを強制しない最適化されたクエリを親切に提供してください(この関数は1回の操作で何千回も実行されるため、速度が非常に重要です-1回で取得しようとしている理由ですクエリ)。ありがとう..

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 行が返された場合は、最初の行を選択します。

EDITこの巨大な構造を使用して、2 番目のクエリのコストを回避することができます。MySQL がうまく処理できるかどうかはわかりませんが、2 番目のクエリを回避できる可能性は十分にあります。

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

偶然にも、これに対するかなりハックな解決策を得ました。これを行う方法は次のとおりです。

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選択自体で回答が得られた場合、句は実際には2番目の値の読み取りを制限します。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

"limit" 句は各クエリから最大 1 行を保証するため、左結合を使用し、"IF()" を使用して "map" レコードの存在を処理できます。

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

上記のクエリは、マップ テーブルの価格と重量を null にすることはできないと想定しています。

于 2012-04-17T14:35:40.003 に答える