2016-05-25 14 views
1

Ich habe eine Reihe von Daten, die mehrere Gruppen von Daten (Vehicle_Code) enthält, jedes Element (PK: Cusip_Sedol) in der Gruppe hat einen bestimmten Code (GIC_Code), der nicht eindeutig ist. Ich versuche, den Prozentsatz jedes Codes (GIC_Code) innerhalb jeder Gruppe (Vehicle_Name) der Daten zu finden. Hier ist meine SQL-Select-Anweisung so weit:Berechnen Prozentsatz der Gruppe mit Group By SQL

SELECT H.vehicle_code, 
     G.group_name, 
     Count(D.cusip_sedol) AS Total 
FROM tbltrading_holdings AS H 
INNER JOIN tbltrading_stocks_data_stocks AS D 
     ON H.cusip_sedol = D.cusip_sedol 
LEFT JOIN tbltrading_gic AS G 
     ON D.gic_code = G.gic_code 
WHERE vehicle_code IN (SELECT vehicle_code 
         FROM tbltrading_vehicles 
         WHERE vehicle_name LIKE 'J%') 
    AND D.gic_code IS NOT NULL 
GROUP BY H.vehicle_code, 
      G.group_name 
ORDER BY vehicle_code 
+0

Es wäre hilfreich, wenn Sie einen Beispieldatensatz mit Tabellenstruktur hinzufügen, damit die Leute eine kleine Testumgebung einrichten können, die Ihnen schneller und genauer hilft. – Reboon

+0

Um den 'vehicle_name' bereitzustellen, mit dem jeder' gic_code' verknüpft ist, müssen Sie einen echten Join machen, nicht ein 'IN' (was effektiv ein' EXISTS' ist). Ist es jedoch möglich, dass der gleiche 'gic_code' an verschiedenen 'vehicle_name'-Werten anknüpft? (Da es einen intermediate 'vehicle_code' gibt, der sie verbindet?) – ErikE

+0

Jedes Fahrzeug hat mehrere cusip_sedols und jedes cusip_sedol hat einen GIC-Code. Jeder GIC-Code ist mehreren cusip_sedolen zugeordnet, und jeder cusip_sedol ist mehreren Fahrzeugen zugeordnet. –

Antwort

0

Ich glaube, Sie ziemlich nah dran sind. Zählt die Sedol für Sie? Wenn ja, dann teilen nur, dass durch die Zählung des Gruppennamens für Ihren Prozentsatz:

SELECT H.vehicle_code, 
     G.group_name, 
     cast(Count(DISTINCT D.cusip_sedol) as DECIMAL)/cast(count(DISTINCT G.group_name) as DECIMAL) AS Total --add this second part 
FROM tbltrading_holdings AS H 
INNER JOIN tbltrading_stocks_data_stocks AS D 
     ON H.cusip_sedol = D.cusip_sedol 
LEFT JOIN tbltrading_gic AS G 
     ON D.gic_code = G.gic_code 
WHERE vehicle_code IN (SELECT vehicle_code 
         FROM tbltrading_vehicles 
         WHERE vehicle_name LIKE 'J%') 
    AND D.gic_code IS NOT NULL 
GROUP BY H.vehicle_code, 
      G.group_name 
ORDER BY vehicle_code 
+0

Wenn ich das tue, bekomme ich insgesamt 1. –

+0

Haben Sie es, müssen Sie nur beide zählen, um sicherzustellen, dass Sie nur diese eindeutige Paarung zählen – EoinS

+0

Verwenden Sie nicht 'float', es ist ein ungenauer Datentyp. Es ist nicht so, dass Sie hier eine solche falsche Antwort bekommen, aber dieses "Floaten" ist inhärent schlecht für alles außer statistischen Zwecken und fortgeschrittener Mathematik, oder Situationen, wo Genauigkeitsverlust * vollständig verstanden * und * gewünscht * ist, wegen der Erhaltung der * Skala *. Verwenden Sie "Dezimal" überall in Ihren Codierungs- und SQL-Tabellen usw., bis Sie einen Fall lernen, in dem "float" wirklich gefordert wird. Ich verspreche dir, dass du ein fortgeschrittener Entwickler sein wirst. – ErikE

0

Was brauchen Sie ist die Summe über alle Reihen. . . und Sie können dies mit Fensterfunktionen erhalten. So ändern sich die Auswahl zu:

SELECT H.vehicle_code, 
     G.group_name, 
     Count(D.cusip_sedol) AS Total, 
     Count(D.Cusip_sedol)*1.0/Sum(Count(D.Cusip_sedol)) Over() as p_total 
. . . 

Beachten Sie, dass die *1.0 ist es nur Integer-Division zu verhindern.

+0

Dies gibt den Prozentsatz jedes GIC_code für jeden Fahrzeug über alle Fahrzeuge. Ich suche den Prozentsatz jedes GIC-Codes für sein jeweiliges Fahrzeug. –

+0

@NickDauphin Deshalb sollten Sie immer Beispieldaten und erwartete Ausgabe einschließen, damit wir wissen, was Sie brauchen. –

1
SELECT 
    H.vehicle_code, 
    G.group_name, 
    VehicleTotal = Count(D.cusip_sedol) OVER (PARTITION BY H.vehicle_code, G.group_name), 
    d.gic_code, 
    gic_codePercentPerVehicleName = 
     Count(d.gic_code) OVER() * 1.0/Count(*) OVER (PARTITION BY V.vehicle_name), 
    gic_codePercentPerVehicleName2 = 
     Count(d.gic_code) * 1.0/Count(*) OVER (PARTITION BY V.vehicle_name) 
FROM 
    dbo.tbltrading_holdings H 
    INNER JOIN tbltrading_stocks_data_stocks D 
     ON H.cusip_sedol = D.cusip_sedol 
    LEFT JOIN dbo.tbltrading_gic G 
     ON D.gic_code = G.gic_code 
    INNER JOIN dbo.tbltrading_vehicles V 
     ON H.vehicle_code = V.vehicle_code 
     AND v.vehicle_name LIKE 'J%' 
WHERE 
    D.gic_code IS NOT NULL 
GROUP BY 
    H.vehicle_code, 
    D.gic_code, 
    G.group_name, 
    V.vehicle_name 
ORDER BY 
    H.vehicle_code 
; 

Es gibt einige Unbekannte hier, die mich gezwungen haben, bestimmte Annahmen zu treffen. Sie können sehen, dass ich zwei verschiedene Interpretationen darüber entwickelt habe, was "Gic Code pro Fahrzeugname" bedeuten könnte.

Für den Anfang ist es die vehicle_name jeder gic_code zugeordnet ist, haben wir eine echte beitreten, kein IN (was effektiv eine EXISTS ist) zu tun. Ist es jedoch möglich, dass gic_code zu verschiedenen vehicle_name Werten zusammengefügt werden? (Da gibt es eine Zwischenstufe vehicle_code, die sie verbindet?) Ich gehe davon aus, dass es nicht möglich ist, dies zu geschehen, und wenn es tatsächlich ist, wird die Abfrage unbrauchbare Ergebnisse geben, und Sie müssen besser was genau formulieren Sie suchen, bevor wir Ihnen mehr helfen können.

Als nächstes werden die Ergebnisse durch die Tatsache verdüstert, dass Sie so viele Spalten auswählen, die sie zwingt, Teil der GROUP BY zu sein. Aber sobald Sie das tun, müssen alle Fensterfunktionen Partitionen enthalten, um sie aus der Gruppierung zu "brechen". Diese Abfrage wird möglicherweise langsam ausgeführt, da sie häufig gleichzeitig ausgeführt wird, was zu vielen Scans der Tabelle führen kann. So wie die Dinge jetzt sind, erhalten Sie für jeden einzelnen gic_code viele Zeilen mit dem gleichen Wert, weil die Abfrage die (mehrere) vehicle_code und group_name Kombinationen für jeden freigibt. Willst du das wirklich?

Sie könnten bessere Ergebnisse erzielen, wenn Sie einige der angezeigten Spalten entfernen, da Sie damit mindestens einen Teil der PARTITION BY Ausdrücke entfernen könnten.

Zuletzt, ich bin mir nicht sicher, ob ich sogar die Partitionen richtig habe. Nur Sie kennen die Kardinalität jeder Spalte in Bezug auf die Joins zu anderen Tabellen.