2017-06-04 101 views
1

我有一個列列表:「user_name」和「特徵」的2列表。每個user_name可能會出現多次不同的特徵。SQL案例聲明IN與組通過

在特徵值是:

  • 在線
  • 店內
  • 帳戶
  • 電子郵件

我想寫一個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的值的標誌。 第二場是他們滿足這一標準,他們符合標準的具有或者「郵件」或「賬戶」

+0

這是無效的標準SQL。你正在使用哪個DBMS? –

+0

@a_horse_with_no_name,我假設你的意思是使用雙引號? (並將它們與單引號混合)。我沒有做太多的工作,因爲他也說代碼不起作用......只是看起來它必須有兩種失敗的方式。仍然會很高興知道DBMS。 –

+0

@runningbirds,做下面的任何答案滿足您的需求?如果是這樣,你應該將其標記爲「已接受」。如果沒有,請回來,讓我們知道如何解決其餘的問題(並回答你使用的是什麼DBMS的問題:例如SQL-Server,MySQL,Oracle,MS-Access,其他東西。 –

回答

1

一個例子結構將有助於更好地瞭解您所要完成的任務。但我想我會得到你想要做的。

您必須使用聚合函數才能使用group by。 類似於SUM或AVG。

但是你首先需要建立自己的數據的一個支點,然後你可以使用該支點來檢查您的標準:

這將創建一個表支點,顯示每個審覈規定符合什麼紀錄:

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表達式:

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 

如果purchase_yn > 0然後你第一個標誌被設置。如果purchase_yn > 0user_with_account > 0那麼你也設置了第二個標誌。

注:你必須從CASE表達式刪除ELSE 0因爲COUNT考慮所有不爲空值。

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

如果我理解正確的,如果用戶擁有「在線」或「店內」,則該用戶想要1爲purchase_yn列,如果用戶也有「電子郵件」或「帳戶」,然後1爲purchaser_with_account列。

如果這是正確的,那麼一個辦法是:

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