

id category user_id text という4つのフィールドがあり、user_id が1のレコードを抽出したい。  
ただし、同じcategory で user_id が5のレコードが存在する場合、そのレコードの方を優先して抽出したい。

そのような構文を組み立てることは出来るでしょうか?  
よろしくお願いいたします。


CC BY-SA 3.0
2016-10-10T06:29:30.097
29450
2016-10-13T04:40:11.167
11105
question
mysql
mysql SELECT 文で、選択的にデータを抽出する

[code]

    SELECT 
      id, category, user_id, text 
    FROM 
      your_table 
    WHERE
      user_id in (1, 5) 
    ORDER BY 
      category, user_id desc
    GROUP BY
      category;
    
[/code]

でいかがでしょうか。（手元ですぐに動作確認できないので、失敗するようでしたら後ほど直します）

user_idが1か5のレコードを抽出し、カテゴリでまとめ、user_idが1と5の両方あるレコードについては5が先になるようにし、最後にGROUP BY
categoryで重複がなくなる（5が優先される）ようになるはずです。


CC BY-SA 3.0
2016-10-10T07:18:33.303
29451
2016-10-10T08:08:32.370
2016-10-10T08:08:32.370
18895
18895
29450
answer


## 解1

whereで`user_id が1のレコード`、left joinで`同じcategory で user_id
が5のレコード`を指定することで条件に合う２レコードを1行で取得できます。

[code]

    select a.*, b.*
    from table1 a
    left join table1 b on a.category = b.category and b.user_id = 5
    where a.user_id = 1;
    
[/code]

<http://sqlfiddle.com/#!9/31d8c/1>

結果の例

[code]

    id  category    user_id text    id  category    user_id text
    2   200 1   b   3   200 5   c
    1   100 1   a   (null)  (null)  (null)  (null)
    
[/code]

最初の４列が`user_id が1のレコード`の情報、5列目以降が`同じcategory で user_id が5のレコード`の情報です。  
`同じcategory で user_id が5のレコード`が存在しなければ5列目以降はnullになります。

SQLの結果を取得して5列目以降がnullかどうかを判定すれば目的の結果が得られます。

## 解2

解1のSQLをサブクエリーにして、外側のselectでuser_id=5が存在するかどうかを判定することでも目的の結果が得られます。

<http://sqlfiddle.com/#!9/31d8c/3>

[code]

    select
      case when id5 is null then id1 else id5 end id,
      case when id5 is null then category1 else category5 end category,
      case when id5 is null then user_id1 else user_id5 end user_id,
      case when id5 is null then text1 else text5 end text
    from (
      select
        a.id id1,
        a.category category1,
        a.user_id user_id1,
        a.text text1,
        b.id id5,
        b.category category5,
        b.user_id user_id5,
        b.text text5
      from table1 a
      left join table1 b on a.category = b.category and b.user_id = 5
      where a.user_id = 1
    ) as sub1
    
[/code]


CC BY-SA 3.0
2016-10-10T07:43:28.903
29453
2016-10-10T12:11:00.843
2016-10-10T12:11:00.843
18862
18862
29450
answer


同一categoryにuser_id
=1かつuser_id=5のレコードがないセットと、user_id=5のセットを取り出すSQLをunionでつないで作ってみました。  
優先抽出の解釈ですが、同一category内にuser_id=5がある場合は、user_id=1のレコードを返さない仕様です。

[code]

    select * from tbl a
    where
        a.user_id = 1
    and
        exists (select 1 from tbl b where a.category = b.category and b.user_id <> 5)
    union
    select * from tbl c
    where
        c.user_id = 5
    
[/code]


CC BY-SA 3.0
2016-10-13T04:40:11.167
29511
2016-10-13T04:40:11.167
10937
29450
answer