37863


内容としてはタイトルで全てですが、うまく表現できていないように思えるため下記に図を記載しました。  
一応、実現することはできたのですが、もう少しシンプルに書けるかと思い質問させて頂きました。（case文などは使わず、外部結合を使用できそうな気がしていますが実現できませんでした。）

### テーブル

[code]

    | name | value |
    |------|-------|
    |   a  |  a1   |
    |   b  |  b1   |
    |   c  |  c1   |
    |   c  |  c2   |
    
[/code]

### 欲しい結果

[code]

    | name | value |
    |------|-------|
    |   a  |  a1   |
    |   b  |  b1   |
    |   c  |  null |
    |   c  |  null |
    
[/code]

### とりあえず作成したSQL

[code]

    select
      h.name
      , case tmp.c 
        when 1 then h.value 
        else null 
        end as value 
    from
      hoge as h
      , ( 
        select
          name
          , count(value) c 
        from
          hoge 
        group by
          name
      ) as tmp 
    where
      h.name = tmp.name 
    order by
      name; 
    
[/code]

### 再現するためのSQL

[code]

    create table hoge(name varchar(10),value varchar(10));
    insert into hoge values('a','a1'),('b','b1'),('c','c1'),('c','c2');
    select * from hoge order by name;
    
[/code]


CC BY-SA 3.0
2017-09-11T04:07:49.287
37862
2017-09-11T06:27:53.117
13022
question
sql
カラム値が重複していない場合にはその値を、そうでない場合にはnullを返すSQLを作成したい


副問い合わせを使用しなくても`count(value)`自体を`case when`で評価すればいいのでは。

[code]

    select
        name
        , case count(value)
          when 1 then min(value)
          else null end 
    from
        hoge 
    group by
        name
    
[/code]


CC BY-SA 3.0
2017-09-11T04:18:49.143
37863
2017-09-11T04:18:49.143
5750
37862
answer


### 外部結合を使う方法

`GROUP BY`と`HAVING`を使って`name`の重複しないテーブルを作成します。

[code]

    SELECT name, MIN(value) AS value
    FROM hoge
    GROUP BY name
    HAVING COUNT(*) = 1;
    
    | name | value |
    |------|-------|
    |   a  |  a1   |
    |   b  |  b1   |
    
[/code]

これを利用して元テーブルに左外部結合します。上記結果に含まれない行は`NULL`になります。

[code]

    SELECT t1.name, t2.value
    FROM hoge AS t1
    LEFT JOIN (SELECT name, MIN(value) AS value
               FROM hoge
               GROUP BY name
               HAVING COUNT(*) = 1) AS t2
    ON t1.name=t2.name
    ORDER BY t1.name;
    
    | name | value |
    |------|-------|
    |   a  |  a1   |
    |   b  |  b1   |
    |   c  |  NULL |
    |   c  |  NULL |
    
[/code]

* * *

### INを使う方法

`GROUP BY`と`HAVING`を使って重複しない`name`だけのテーブルを作成します。

[code]

    SELECT name
    FROM hoge
    GROUP BY name
    HAVING COUNT(*) = 1;
    
    | name |
    |------|
    |   a  |
    |   b  |
    
[/code]

`IN`を使ってこのテーブルに含まれているかを判定します。

[code]

    SELECT name, CASE WHEN name IN (SELECT name FROM hoge GROUP BY name HAVING COUNT(*)=1)
                 THEN value
                 END AS value
    FROM hoge
    ORDER BY name;
    
    | name | value |
    |------|-------|
    |   a  |  a1   |
    |   b  |  b1   |
    |   c  |  NULL |
    |   c  |  NULL |
    
[/code]


CC BY-SA 3.0
2017-09-11T06:27:53.117
37866
2017-09-11T06:27:53.117
4236
37862
answer