2016-04-11 5 views
0

Ich habe eine typische Benutzertabelle zusätzlich zu der folgenden Feature-TabelleSQL: Zählt eindeutig Benutzer mit Bedingungen basierend auf viele zu viele Tabellen

Features:

----------------------- 
| userId | feature | 
----------------------- 
| 1 | account | 
| 1 | hardware | 
| 2 | account | 
| 3 | account | 
| 3 | hardware | 
| 3 | extra | 
----------------------- 

Grundsätzlich versuche ich, einige zu bekommen zählt zu Berichtszwecken. Insbesondere versuche ich die Anzahl der Benutzer mit Konten und Hardware zusammen mit der Gesamtzahl der Konten zu finden.

Ich weiß, ich kann das tun, nach der Gesamtzahl der Konten

SELECT 
    COUNT(DISTINCT userId) as totalAccounts 
FROM features 
WHERE feature = "account"; 

Ich bin nicht sicher, zu erhalten, wie wenn die Anzahl der Benutzer mit beiden Konten und Hardware zu bekommen. In diesem Beispiel-Dataset ist die Nummer, nach der ich suche. Benutzer 1 und 3 haben beide Konten und Hardware.

Ich würde es vorziehen, dies in einer einzigen Abfrage zu tun. Möglicherweise CASE mit (Beispiel für totalAccounts unten):

SELECT 
    COUNT(DISTINCT(CASE WHEN feature = "account" THEN userId END)) as totalAccounts, 
    COUNT(?) as accountsWithHardware 
FROM features; 

Antwort

0

Dies sind zwei Abfragen - ein für die gesamte Benutzeranzahl, eine für die Zwei-Funktionen Benutzeranzahl - dass Sie mit einem Cross-Join verbinden können:

select 
    count_all_users.cnt as all_user_count, 
    count_users_having_both.cnt as two_features_user_count 
from 
(
    select count(distinct userid) as cnt 
    from features 
) count_all_users 
cross join 
(
    select count(*) as cnt 
    from 
    (
    select userid 
    from features 
    where feature in ('account', 'hardware') 
    group by userid 
    having count(*) = 2 
) users_having_both 
) count_users_having_both; 

UPDATE: Mit etwas Nachdenken gibt es einen viel einfacheren Weg. Gruppieren Sie nach Benutzer und erkennen Sie, ob Feature 1 und Feature 2 vorhanden sind. Dann zähle.

select 
    count(*) as all_user_count, 
    count(case when has_account = 1 and has_hardware = 1 then 1 end) 
    as two_features_user_count 
from 
(
    select 
    userid, 
    max(case when feature = 'account' then 1 else 0 end) as has_account, 
    max(case when feature = 'hardware' then 1 else 0 end) as has_hardware 
    from features 
    group by userid 
) users;