2016-05-12 7 views
4

Mit MSSQLAggregieren SQL Ergebnisse, zwei Tabellen, dann zusammenfassend Ergebnisse

Ich habe eine Tabelle von Benutzern, und eine Tabelle der Erzeugnisse, auf die sie abonniert haben. Diese Abonnements sind entweder Frei (F) oder Bezahlt (P). Ich bin den Tabellen beigetreten, habe den F/P-Wert mit einer case-Anweisung in numerisch umgewandelt und dann die Werte nach Benutzer-ID summiert. Die Idee ist, dass jeder mit nur kostenlosen Konten die Summe 0 hat, diejenigen mit mindestens einem bezahltes Konto einen Wert von 1 oder höher. Ich habe bis hierher mit folgendem bekommen:

SELECT t1.user_id, SUM(
    CASE 
     WHEN t2.free_paid = 'P' 
      THEN 1 
     ELSE 0 
    END) as highest 
FROM users t1 INNER JOIN accounts t2 
    ON t1.user_id = t2.user_id 
WHERE t2.account = 'A' 
GROUP BY t1.user_id 
ORDER BY t1.user_id 

Daraus ergibt sich ein Ergebnis wie:

755 2 
1259 2 
2031 1 
3888 0 

Was bedeutet, dass alle, aber 3888 haben mindestens ein Konto bezahlt.

Aber jetzt möchte ich diese einfach addieren, um unsere zwei Werte zu erhalten, eine Anzahl von Benutzern mit mindestens einem bezahlten Konto (3 im Beispiel), und eine Zählung von denen mit nur kostenlosen Konten (1 in Beispiel).

Ich versuchte, erklären zwei Variablen, z. @free und @paid und verwenden Sie eine case-Anweisung, um diese Werte hinzuzufügen, indem Sie die oben genannten Elemente umschließen und sie als Unterabfrage behandeln, aber ich kann den Lauf nicht ausführen.

Irgendwelche Ideen?

+1

Was ist das erwartete Ergebnis? –

+0

Für die oben genannten Daten, Bezahlt: 3, Kostenlos: 1 – SwS

Antwort

3

Wiederverwendung der Abfrage von der Frage, können Sie einen CTE erstellen (oder eine Unterabfrage) und aggregieren die Ergebnisse:

;WITH CTE_UserAccounts AS (
    SELECT t1.user_id, SUM(
     CASE 
      WHEN t2.free_paid = 'P' 
       THEN 1 
      ELSE 0 
     END) as highest 
    FROM users t1 INNER JOIN accounts t2 
     ON t1.user_id = t2.user_id 
    WHERE t2.account = 'A' 
    GROUP BY t1.user_id 
) 
SELECT 
    COUNT(CASE WHEN highest > 0 THEN 1 END) AS [Paid], 
    COUNT(CASE WHEN highest = 0 THEN 1 END) AS [Free] 
FROM 
    CTE_UserAccounts; 
+0

Das funktioniert auch, und ich schätze den Einblick in die Verwendung von CTE, um dieses Problem zu lösen. – SwS

1
SELECT 
COUNT(DISTINCT CASE WHEN t2.free_paid = 'P' THEN t1.user_id END) as atleast_one_paid, 
COUNT(DISTINCT CASE WHEN t2.free_paid <> 'P' THEN t1.user_id END) as onlyfree 
FROM users t1 
INNER JOIN accounts t2 ON t1.user_id = t2.user_id 
WHERE t2.account = 'A' 
+0

Tatsächlich wird 'onlyfree' eine Anzahl von verschiedenen Benutzern mit mindestens einem kostenlosen Konto sein, da nichts die Abfrage daran hindert, einen Benutzer mit mindestens einem kostenlosen Konto zu zählen und mindestens ein kostenpflichtiges Konto in beiden Spalten. –

1

Sie nur um Ihre ursprüngliche Abfrage wickeln konnte und es zusammenzufassen

SELECT SUM (case when highest > 0 THEN 1 else 0 END) as UsersWithPaidAccount, 
SUM (case when highest = 0 THEN 1 else 0 END) as UsersWithOnlyFreeAccount 
FROM (SELECT t1.user_id, SUM(
    CASE 
     WHEN t2.free_paid = 'P' 
      THEN 1 
     ELSE 0 
    END) as highest 
FROM users t1 INNER JOIN accounts t2 
    ON t1.user_id = t2.user_id 
WHERE t2.account = 'A' 
GROUP BY t1.user_id) 
as DerivedTable 
+0

Das funktioniert, vielen Dank! – SwS

Verwandte Themen