2

2つのテーブルabがあるとします。列IDはテーブルaで一意ですが、テーブルbに複数のエントリがあり、列xとそのテーブルの他の列の値が異なります。テーブルbの主キーは(id、x)です。

次のようにMAXで実行できるように、 bからSELECTクエリに単一の行を結合できる必要があります。

SELECT * FROM a
INNER JOIN b USING(id)
WHERE b.x = (SELECT MAX(x) FROM b WHERE b.id = a.id)

MAXでは、これは問題なく機能します。しかし、MAXは必要ありません。私は実際にこのようなものが必要です:

SELECT * FROM a
INNER JOIN b USING(id)
WHERE b.x = (SELECT x FROM b 
             WHERE x IN (2,3,7) OR x IS NULL
             ORDER BY FIELD(x,3,2,7) DESC
             LIMIT 1)

私のMySQLバージョンはこのサブクエリでLIMITをサポートしていないため、このクエリは失敗します。私が提供した順序で少なくとも1つの行を確実に結合する別の方法はありますか?

私がやろうとしていることの概略図は次のようになります。

Select * from table a for each id
Join table b where x = 7
If no entry in b exists where a.id=b.id and x = 7, join b where x = 2
If no entry in b exists where a.id=b.id and x IN (2,7), join b where x = 3
If no entry in b exists where a.id=b.id and x IN (2,3,7), join b where x IS NULL

私にはこの必要性があります:

  • 必要なこの特定のコードでは、複数のクエリを使用することはできません。それは1つの魔法のオールインワンクエリでなければなりません
  • INNER JOIN(SELECT *)ステートメントを使用できません
  • IDが複数回存在するクエリを実行することはできません(したがって、テーブルbの値が異なる可能性があるため、DISTINCTはオプションではありません)
  • テーブルbにa.idのエントリがあり、xが2、3、7、またはNULLのいずれかであることは確かですが、どちらかはわかりません。また、a.idのエントリがいくつあるかもわかりません。表b。
  • MySQLのアップグレードは、このコードが私の顧客の汎用サーバーで機能する必要があるため、最善のオプションではありません

つまり、私の質問は、MAX値の代わりに特定の順序を考慮に入れることができるMAXに似た関数はありますか?

前もって感謝します!

4

2 に答える 2

1

これを行うには、各 X の順序の重みを手動で指定します。

mysql> select * from aa;
+----+------+
| id | name |
+----+------+
|  1 | John |
|  2 | Ted  |
|  3 | Jill |
|  4 | Jack |
+----+------+
4 rows in set (0.00 sec)

mysql> select * from bb;
+------+------+------------+
| id   | x    | class      |
+------+------+------------+
|    1 |    7 | HighPriori |
|    1 |    2 | MediumPrio |
|    1 |    3 | LowPriorit |
|    2 |    2 | Medium     |
|    2 |    3 | Low        |
|    3 |    3 | Low only   |
+------+------+------------+
5 rows in set (0.00 sec)


select version();
+-------------+
| version()   |
+-------------+
| 5.5.25a-log |
+-------------+

SELECT aa.name, bb.x, bb.class
    FROM aa LEFT JOIN bb ON (aa.id = bb.id AND bb.x IN (2,3,7)
        AND bb.x = ( SELECT x FROM bb WHERE bb.id = aa.id AND x IN (2,3,7)
           ORDER BY CASE
               WHEN x = 7 THEN 100
               WHEN x = 2 THEN 200
               WHEN x = 3 THEN 300
               ELSE 400
           END LIMIT 1 )
    );

最も内側SELECTは優先度に基づいて X の最も適切な値を選択します: 利用可能な場合は 7、そうでない場合は 2、そうでない場合は 3。 、しかし 2 は 3 よりも高いです。

LEFT JOIN、存在する場合はその 1 つのレコードに一致し、存在NULLしない場合は に一致します。

ジョンは 2、3、7 を持っていて 7 レコードを取得しますが、テッドは 2 と 3 を持っていて 2 を取得します。

+------+------+------------+
| name | x    | class      |
+------+------+------------+
| John |    7 | HighPriori |
| Ted  |    2 | Medium     |
| Jill |    3 | Low only   |
| Jack | NULL | NULL       |
+------+------+------------+

(厳密に言えば、IN (2,3,7)inSELECTELSEinCASEは冗長です。どちらでもかまいません)。

困っCASEている...

X フィールドがすでに順序を確立している場合、たとえば、値 3,2,7 を 2 - 3 - 7 または 7 - 3 - 2 のいずれかの数値順序で指定したい場合は、CASE: の代わりに :なしで実行できます。

       ORDER BY CASE
           WHEN x = 7 THEN 100
           WHEN x = 2 THEN 200
           WHEN x = 3 THEN 300
           ELSE 400
       END 

あなたはただ指定することができます

       ORDER BY x

また

       ORDER BY x DESC

... x にインデックスが付けられていても、パフォーマンスの向上はわずかですが、 X の値が非常に多い場合、それらすべてを で指定するのはCASE厄介であり、例外の調査には時間がかかる場合があります。

しかし、オブジェクトをこの順序にしたいと考えてみましょう

       First                          Last
       20,21,22,23,40,41,42,9,1,2,3,4,5

これは通常、X が 1 ~ 5 の値で unsigned と宣言されたときに発生し (「これ以上のクラスは必要なく、常に1 が最初になります!」)、数週間後に誰かが「これは新しいエキサイティングな製品です。行かなければなりません」と追加します。最初!" 例外に9を割り当て、最後に「次の製品シリーズのために2Xと4Xで始まるまったく新しいXYクラスを追加しましょう...」で再び発生します。これは次のように行うことができます

       WHEN x <= 5 THEN 900+x
       WHEN x = 9   THEN 809
       ELSE 700 + x

上記のごちゃ混ぜセットを順序付けられたシーケンスで翻訳します

720,721,722,723,740,741,742,809,901,902,903,904,905

3 つWHENの s を使用すると、すべての作業を実行できます。

于 2012-10-23T08:22:12.573 に答える
0
SELECT * FROM a
INNER JOIN b USING(id)
WHERE b.x = (SELECT x FROM b 
             WHERE x IN (2,3,7) OR x IS NULL
             ORDER BY FIELD(x,3,2,7) DESC
             LIMIT 1)

サブクエリをジョインに切り替える

SELECT * FROM a
join ( SELECT x FROM b 
             WHERE x,id IN (2,3,7) OR x IS NULL
             ORDER BY FIELD(x,3,2,7) DESC
             LIMIT 1) as X on X.id = a.id 
于 2012-10-23T08:05:42.980 に答える