2017-06-04 18 views
1

私はカラムが "user_name"と "characteristic"の2列テーブルを持っています。各user_nameは、異なる特性を持つ複数回表示されることがあります。sql caseステートメントIN with group by

特性値は以下のとおりです。

  • オンライン
  • のInStore
  • アカウント
  • 私はこのように書きSQL文を書きたいメール

- しかし、明らかに、このは動作していません:

SELECT user_name, 
     case 
      when characteristic in ("online","instore") then 1 
      else 0 
     END as purchase_yn, 
     case 
      when characteristic in ("online","instore") and 
       characteristic in ("email",'account') then 1 
      else 0 
     END as purchaser_with_account 
FROM my_table 
GROUP BY user_name; 

最初のフラグは、そのuser_nameのいずれかの値の存在をチェックするフラグです。

SELECT user_name, 
     COUNT(case when characteristic in ("online","instore") then 1 END) as purchase_yn, 
     COUNT(case when characteristic in ("email",'account') then 1 END) as user_with_account 
FROM my_table 
GROUP BY user_name 

の場合: 第二フィールドは、彼らがこの基準を満たしており、彼らは「メール」または「アカウント」

+0

これは無効な標準のSQLです。どのDBMSを使用していますか? –

+0

@a_horse_with_no_name、二重引用符を使用しているとしますか? (そして一重引用符でそれらを混ぜる)。私はコードがうまくいかないと言ったので、私はあまりそれを作っていませんでした...それは失敗する2つの方法がなければならないように見えます。それでもDBMSを知っておくとよいでしょう。 –

+0

@runningbirds、あなたのニーズを満たす下記の答えをお試しください。もしそうなら、あなたはそれを「受け入れられた」とマークするべきです。そうでない場合、戻って残りの問題について教えてください(そしてSQL Server、MySQL、Oracle、MS-Access、その他のものなど、使用しているDBMSの質問に答えてください)。 –

答えて

1

例データの構造は、より良いあなたが達成しようとしているのか理解に役立つだろう。しかし、私はあなたがしようとしているものを得ると思う。

でグループを使用するには、集計関数を使用する必要があります。 SUMやAVGのようなものです。

は、しかし、あなたはあなたのデータのピボットを構築するために最初に必要があると、あなたはあなたのcriteriasをチェックするためにそのピボットを使用することができます。

これはのcriteriasが満たされているものをレコードごとに示す表のピボットを作成します。

SELECT 
    user_name, 
    case when characteristic = "online" then 1 else 0 end as online_yn, 
    case when characteristic = "instore" then 1 else 0 end as instore_yn, 
    case when characteristic = "account" then 1 else 0 end as account_yn, 
    case when characteristic = "email" then 1 else 0 end as email_yn, 
FROM my_table 

これらのエントリの平均化バージョンをuser_nameにグループ化して作成し、それらの平均値を使用して、必要なフィールドを作成します。そのためには、前にインラインテーブルとして作成したものと同じステートメントを使用する必要があります。

Select 
    user_name, 
    case when avg(online_yn + instore_yn) >= 1 then 1 else 0 end as purchase_yn, 
    case when avg(online_yn + instore_yn) >= 1 and avg(email_yn + account_yn) >= 1 then 1 else 0 end as purchaser_with_account 
From 
    (SELECT 
     user_name, 
     case when characteristic = "online" then 1 else 0 end as online_yn, 
     case when characteristic = "instore" then 1 else 0 end as instore_yn, 
     case when characteristic = "account" then 1 else 0 end as account_yn, 
     case when characteristic = "email" then 1 else 0 end as email_yn, 
    FROM my_table) avg_table 

group by 
    user_name; 

これは役に立ちます。

パフォーマンス面で効率的ではないかもしれませんが、あなたが望むものを得るでしょう。

+0

私は間違いなくこのためにAVGを使用してください。MAXまたはSUMのほうがずっと適切です。 –

0

のいずれかを有するための基準を満たしていることをあなただけCOUNT集合体でCASE式を囲む必要があるということですpurchase_yn > 0最初のフラグが設定されます。 purchase_yn > 0user_with_account > 0の場合、2番目のフラグも設定されます。

注:COUNTは、アカウントにすべてnullではない値を取るので、あなたがCASE表現からELSE 0を削除する必要があります。

0

あなたは、特定のRDBMSに言及していないが、SUM(DISTINCT ...)が利用可能な場合は、次のは非常にいいです:

SELECT 
    username, 
    SUM(DISTINCT 
     CASE 
      WHEN characteristic in ('online','instore') THEN 1 
      ELSE 0 
     END) AS purchase_yn, 
    CASE WHEN (
     SUM(DISTINCT 
      CASE 
       WHEN characteristic in ('online','instore') THEN 1 
       WHEN characteristic in ('email','account') THEN 2 
      ELSE 0 END 
     ) 
    ) = 3 THEN 1 ELSE 0 END as purchaser_with_account 
FROM 
    my_table 
GROUP BY 
    username 
0

もし私が正しく理解しているのであれば、ユーザーは「purchase_yn」とし、ユーザーにも「電子メール」または「アカウント」がある場合はpurchaser_with_accountの1を入力してください。

これが正しい場合は、一つの方法は次のとおりです。

with your_table(user_name, characteristic) as(
    select 1, 'online' union all 
    select 1, 'instore' union all 
    select 1, 'account' union all 
    select 1, 'email' union all 
    select 2, 'account' union all 
    select 2, 'email' union all 
    select 3, 'online' 
) 

-- below is actual query: 

select your_table.user_name, coalesce(max(t1.purchase_yn), 0) as purchase_yn, coalesce(max(t2.purchaser_with_account), 0) as purchaser_with_account 
from your_table 
left join (SELECT user_name, 1 as purchase_yn from your_table where characteristic in('online','instore')) t1 
on your_table.user_name = t1.user_name 
left join (SELECT user_name, 1 as purchaser_with_account from your_table where characteristic in('email', 'account')) t2 
on t1.user_name = t2.user_name 
group by your_table.user_name