4

以下の表のようなデータを使用します。

|  id  |    e_date    |  e_time |  place | person| ref  |ref_type| 
|  10  |  2015-08-03  |  10:30  |  work  |  tony | 1234 |   A    |
|  25  |  2015-08-03  |  10:30  |  work  |  NULL | NULL |   A    |
|  37  |  2015-08-03  |  NULL   |  work  |  tony | NULL |   A    |
|  99  |  2015-08-03  |  10:30  |  work  |  fred | 1234 |   B    |

MySQL句 で一連の条件 (desc の重要性) の最初の一致のみを取得する最良の方法は何ですか?WHERE

  • refフィールド に合わせる
  • フィールドで一致しない場合は、refフィールドで一致しe_date+e_time+placeます
  • 一致がない場合、refまたはe_date+e_time+place一致する場合e_date+place+person

ここでの目的は、降順の一連の基準に基づいて、最適な単一行一致を取得し、前の基準が満たされない場合にのみ基準を使用することです。

クエリの最初の試みは次のようになりました。

SELECT id FROM my_table 
WHERE ref_type = 'A' AND (
  ref = '1234'
  OR
  (e_date = '2015-08-03' AND e_time = '10:30' AND place = 'work')
  OR
  (e_date = '2015-08-03' AND place = 'work' AND person = 'tony')
)

しかし、OR包括的(シーケンシャルではない)であるため、これは行10を返します-このsqlfiddle25を参照してください37

( に変更した場合ORDER BY ref DESC)できますが、値がなく、2 番目または 3 番目の条件のいずれかによって区別する必要がある場合、それは役に立ちません。LIMIT 1SELECT id, ref FROM...ref

私の次の試みは、次のような句でネストされたIF条件を使用します。WHERE

SELECT id FROM my_table 
WHERE ref_type = 'A' AND (
  IF(ref = 1234, 
    ref = 1234,
    IF(e_date = '2015-08-03' AND e_time = '10:30' AND place = 'work', 
       e_date = '2015-08-03' AND e_time = '10:30' AND place = 'work',
       e_date = '2015-08-03' AND place = 'work' AND person = 'tony'
    )
  )
)

ただし、これは rows も返します10-この sqlfiddle2537参照してください

また、使用してみましたIFNULL

SELECT id FROM my_table 
WHERE ref_type = 'A' AND 
  IFNULL(ref = '1234', 
    IFNULL(e_date = '2015-08-03' AND e_time = '10:30' AND place = 'work',
      e_date = '2015-08-03' AND place = 'work' AND person = 'tony')
  )

10行を返します25 -このsqlfiddleを参照してください

このクエリを記述する最良の方法は何ですか?

私はphpを使用しています.3つの別々の順次クエリを実行し、各結果に対してphp条件を使用することもできます.

4

4 に答える 4

3

(私が知っている)唯一の方法は、異なる .xml でクエリを複数回実行することwhereです。これは、ユニオンを使用した単一のクエリとして実行できます。

SELECT * FROM (
    SELECT <stuff> FROM <table> WHERE <most important condition> LIMIT 1
    UNION
    SELECT <stuff> FROM <table> WHERE <less important condition> LIMIT 1
    UNION
    SELECT <stuff> FROM <table> WHERE <even less important condition> LIMIT 1
    UNION
    ...
) as t
LIMIT 1

または、それらを 1 つずつ実行して、結果があれば停止することもできます。

于 2015-07-07T09:27:32.763 に答える
0

case when in where を試す必要があります。

SELECT id FROM my_table 
WHERE 
1 = case when ref_type = 'A' then 1 
    else
        case when ref = '1234' then 1 
        else
            case when (e_date = '2015-08-03' AND e_time = '10:30' AND place = 'work') or (e_date = '2015-08-03' AND place = 'work' AND person = 'tony') then 1 else 0 end 
        end
    end 

いずれかが基準を満たす場合、昇順で条件をチェックし、それ以上はチェックしません。

あなたの正確な条件がわからないので、あなたのニーズを満たすためにその方法を使用する必要がある参考のためにここに入れました.

于 2015-07-07T10:07:36.693 に答える
0

私があなたのロジックを理解してrefいれば、null でない場合に行を返す必要があります。null の場合は、null でe_timeないもの。そして最後に、personnull でないもの。では、この順序付けを最初のクエリに使用できますか?

SELECT id FROM my_table 
WHERE ref_type = 'A' AND (
  ref = '1234'
  OR
  (e_date = '2015-08-03' AND e_time = '10:30' AND place = 'work')
  OR
  (e_date = '2015-08-03' AND place = 'work' AND person = 'tony')
)
ORDER BY ref DESC,
  e_time DESC,
  person DESC 
LIMIT 1 ;
于 2015-07-07T09:37:31.027 に答える