Hoe bereken je een percentage met een SQL-statement

Ik heb een SQL Server-tabel die gebruikers & hun cijfers. Laten we voor de eenvoud zeggen dat er 2 kolommen zijn – name& grade. Een typische rij is dus Naam: “John Doe”, Graad: “A”.

Ik ben op zoek naar één SQL-instructie die de percentages van alle mogelijke antwoorden zal vinden. (A, B, C, etc…) Is er ook een manier om dit te doen zonder alle mogelijke antwoorden te definiëren (open tekstveld – gebruikers kunnen ‘pass/fail’, ‘none’, etc…)

De uiteindelijke output die ik zoek is A: 5%, B: 15%, C: 40%, enz…


Antwoord 1, autoriteit 100%

Ik heb het volgende getest en dit werkt. Het antwoord van gordyii was dichtbij, maar had de vermenigvuldiging van 100 op de verkeerde plaats en had een paar ontbrekende haakjes.

Select Grade, (Count(Grade)* 100 / (Select Count(*) From MyTable)) as Score
From MyTable
Group By Grade

Antwoord 2, autoriteit 97%

  1. De meest efficiënte (met over()).

    select Grade, count(*) * 100.0 / sum(count(*)) over()
    from MyTable
    group by Grade
    
  2. Universeel (elke SQL-versie).

    select Grade, count(*) * 100.0 / (select count(*) from MyTable)
    from MyTable
    group by Grade;
    
  3. Met CTE, de minst efficiënte.

    with t(Grade, GradeCount) 
    as 
    ( 
        select Grade, count(*) 
        from MyTable
        group by Grade
    )
    select Grade, GradeCount * 100.0/(select sum(GradeCount) from t)
    from t;
    

Antwoord 3, autoriteit 16%

In plaats van een afzonderlijke CTE te gebruiken om het totaal te krijgen, kunt u een vensterfunctie gebruiken zonder de “partitie door” -clausule.

Als u gebruikt:

count(*)

Om de graaf voor een groep te krijgen, kunt u gebruiken:

sum(count(*)) over ()

Om de totale telling te krijgen.

Bijvoorbeeld:

select Grade, 100. * count(*) / sum(count(*)) over ()
from table
group by Grade;

Het heeft de neiging om sneller te zijn in mijn ervaring, maar ik denk dat het in sommige gevallen intern een temp-tabel kan gebruiken (ik heb “werkbare” gezien tijdens het uitvoeren met “Statistieken io op”).

bewerken:
Ik weet niet zeker of mijn voorbeeldquery is wat u zoekt, ik illustreerde gewoon hoe de vensterfuncties werken.


Antwoord 4, Autoriteit 5%

Ik gebruik dit gewoon wanneer ik ooit een percentage nodig heb.

ROUND(CAST((Numerator * 100.0 / Denominator) AS FLOAT), 2) AS Percentage

Merk op dat 100.0 1 decimaal retourneert, terwijl 100 op zijn eigen het resultaat zal afronden naar het dichtstbijzijnde hele getal, zelfs met de ronde (…, 2) functie!


Antwoord 5, Autoriteit 4%

U moet het totaal van cijfers berekenen
Als het SQL 2005 is, kunt u CTE

gebruiken

   WITH Tot(Total) (
    SELECT COUNT(*) FROM table
    )
    SELECT Grade, COUNT(*) / Total * 100
--, CONVERT(VARCHAR, COUNT(*) / Total * 100) + '%'  -- With percentage sign
--, CONVERT(VARCHAR, ROUND(COUNT(*) / Total * 100, -2)) + '%'  -- With Round
    FROM table
    GROUP BY Grade

Antwoord 6, Autoriteit 3%

Je moet groeperen in het cijferveld. Deze zoekopdracht zou u in vrijwel elke database moeten geven wat u zoekt.

   Select Grade, CountofGrade / sum(CountofGrade) *100 
    from
    (
    Select Grade, Count(*) as CountofGrade
    From Grades
    Group By Grade) as sub
    Group by Grade

Je moet het systeem specificeren dat je gebruikt.


Antwoord 7, autoriteit 3%

Het volgende zou moeten werken

ID - Key
Grade - A,B,C,D...

EDIT: de * 100verplaatst en de 1.0toegevoegd om ervoor te zorgen dat er geen gehele deling wordt uitgevoerd

Select 
   Grade, Count(ID) * 100.0 / ((Select Count(ID) From MyTable) * 1.0)
From MyTable
Group By Grade

Antwoord 8, autoriteit 2%

Dit is, geloof ik, een algemene oplossing, hoewel ik het heb getest met IBM Informix Dynamic Server 11.50.FC3. De volgende vraag:

SELECT grade,
       ROUND(100.0 * grade_sum / (SELECT COUNT(*) FROM grades), 2) AS pct_of_grades
    FROM (SELECT grade, COUNT(*) AS grade_sum
            FROM grades
            GROUP BY grade
         )
    ORDER BY grade;

geeft de volgende output op de testgegevens die onder de horizontale regel worden getoond. De functie ROUNDkan DBMS-specifiek zijn, maar de rest (waarschijnlijk) niet. (Merk op dat ik 100 heb gewijzigd in 100,0 om ervoor te zorgen dat de berekening plaatsvindt met niet-geheel getal – DECIMAAL, NUMERIEK – rekenkundig; zie de opmerkingen en dankzij Thunder.)

grade  pct_of_grades
CHAR(1) DECIMAL(32,2)
A       32.26
B       16.13
C       12.90
D       12.90
E       9.68
F       16.13

CREATE TABLE grades
(
    id VARCHAR(10) NOT NULL,
    grade CHAR(1) NOT NULL CHECK (grade MATCHES '[ABCDEF]')
);
INSERT INTO grades VALUES('1001', 'A');
INSERT INTO grades VALUES('1002', 'B');
INSERT INTO grades VALUES('1003', 'F');
INSERT INTO grades VALUES('1004', 'C');
INSERT INTO grades VALUES('1005', 'D');
INSERT INTO grades VALUES('1006', 'A');
INSERT INTO grades VALUES('1007', 'F');
INSERT INTO grades VALUES('1008', 'C');
INSERT INTO grades VALUES('1009', 'A');
INSERT INTO grades VALUES('1010', 'E');
INSERT INTO grades VALUES('1001', 'A');
INSERT INTO grades VALUES('1012', 'F');
INSERT INTO grades VALUES('1013', 'D');
INSERT INTO grades VALUES('1014', 'B');
INSERT INTO grades VALUES('1015', 'E');
INSERT INTO grades VALUES('1016', 'A');
INSERT INTO grades VALUES('1017', 'F');
INSERT INTO grades VALUES('1018', 'B');
INSERT INTO grades VALUES('1019', 'C');
INSERT INTO grades VALUES('1020', 'A');
INSERT INTO grades VALUES('1021', 'A');
INSERT INTO grades VALUES('1022', 'E');
INSERT INTO grades VALUES('1023', 'D');
INSERT INTO grades VALUES('1024', 'B');
INSERT INTO grades VALUES('1025', 'A');
INSERT INTO grades VALUES('1026', 'A');
INSERT INTO grades VALUES('1027', 'D');
INSERT INTO grades VALUES('1028', 'B');
INSERT INTO grades VALUES('1029', 'A');
INSERT INTO grades VALUES('1030', 'C');
INSERT INTO grades VALUES('1031', 'F');

Antwoord 9, autoriteit 2%

SELECT Grade, GradeCount / SUM(GradeCount)
FROM (SELECT Grade, COUNT(*) As GradeCount
      FROM myTable
      GROUP BY Grade) Grades

Antwoord 10

In elke SQL Server-versie zou u een variabele kunnen gebruiken voor het totaal van alle cijfers zoals deze:

declare @countOfAll decimal(18, 4)
select @countOfAll = COUNT(*) from Grades
select
Grade,  COUNT(*) / @countOfAll * 100
from Grades
group by Grade

Antwoord 11

U kunt een subselect gebruiken in uw van query (niettest en niet zeker wat sneller is):

SELECT Grade, COUNT(*) / TotalRows
FROM (SELECT Grade, COUNT(*) As TotalRows
      FROM myTable) Grades
GROUP BY Grade, TotalRows

of

SELECT Grade, SUM(PartialCount)
FROM (SELECT Grade, 1/COUNT(*) AS PartialCount
      FROM myTable) Grades
GROUP BY Grade

of

SELECT Grade, GradeCount / SUM(GradeCount)
FROM (SELECT Grade, COUNT(*) As GradeCount
      FROM myTable
      GROUP BY Grade) Grades

U kunt ook een opgeslagen procedure gebruiken (excuses voor de Firebird Syntaxis):

SELECT COUNT(*)
FROM myTable
INTO :TotalCount;
FOR SELECT Grade, COUNT(*)
FROM myTable
GROUP BY Grade
INTO :Grade, :GradeCount
DO
BEGIN
    Percent = :GradeCount / :TotalCount;
    SUSPEND;
END

Antwoord 12

Ik had hier een soortgelijk probleem. U moet in staat zijn om het juiste resultaat te vermenigvuldigen met 1,0 in plaats van 100.See-voorbeeldafbeelding bijgevoegd

Selecteer Grade, (telling (cijfer) * 1.0 / (selecteer telling (*) van mytable)) als score van MyTable Group per cijfer


Antwoord 13

Deze werkt goed in MS SQL. Het transformeert varchar naar het resultaat van twee decimalen-gelimiteerde float.

Select field1, cast(Try_convert(float,(Count(field2)* 100) / 
Try_convert(float, (Select Count(*) From table1))) as decimal(10,2)) as new_field_name 
From table1 
Group By field1, field2;

Other episodes