[MS SQL] Zlicz liczbę kontrahentów generujących 80% obrotu.

0

Witajcie, jak w temacie, pracuję nad raportem w którym jednym z elementów jest zliczenie liczby klientów, którzy generują 80% całościowego obrotu. Tabelę mam w prostej formie:
ID Klienta || Obrót miesięczny. Proszę podpowiecie co nieco ? :)

1

Źle zdefiniowane zadanie.

0

@Marcin.Miga: ale można ten błąd w założeniach wykorzystać na naszą korzyść: bierzesz po kolei kontrahentów i dodajesz, aż suma osiągnie wartość 80% ;)
Nigdzie nie jest napisane, że to mają być najwięksi, prawda? :D

0

Kurde no znęcacie się tak z poniedziałku :) Oczywiście, że chodzi o największych. To o zasadę Pareto się ociera.

0

No a zastanów się, jak byś to zrobił - nie w SQL, ale zwyczajnie, np. przeglądając segregator z zestawieniami, albo działając w excelu.
Ja bym posegregował kontrahentów malejąco po obrotach, a następnie zaczął sumowanie i tak sobie dodawał obroty aż do chwili, w której uzyskana suma przekroczy zadany próg. Pewnie sposobów realizacji tego zadania jest pełno, ale ten wydaje się najprostszy.

1

tak właśnie robiłem do dziś, bo zestawienie przygotowywałem raz w miesiącu, ale teraz będę to robił codziennie na bazie 10 000 klientów. Zaczyna być dużo "wyklejanek" w excelu i łatwo o błąd. Chciałem to złapać z poziomu tabeli źródłowej. Orderować potrafię tu filozofii nie ma, tylko ten moment sumy narastającej do konkretnego momentu 80% całości przychodu.

0

No OK, ale skoro działasz w SQL, to zakładam, że łączysz się z nim z wykorzystaniem jakiegoś języka programowania - chociażby PHP, Pythona czy C++.

W związku z tym możesz albo rozkminiać, jak to wrzucić w zapytanie - z wykorzystaniem WHILE - https://stackoverflow.com/questions/19891594/in-sql-server-how-to-create-while-loop-in-select oraz SUM - https://www.w3schools.com/sql/sql_count_avg_sum.asp, aczkolwiek tutaj można się łatwo zakręcić, albo po prostu zrobić zwykłe SELECT * FROM xxx ORDER BY i z poziomu aplikacji wczytywać sobie kolejne wartości i zwiększać sumę obrotów o wartość obrotu danego klienta, aż do czasu, kiedy osiągniemy zadany pułap.

Drugie rozwiązanie może jest mniej hackerskie i PRO, ale całkowicie załatwi temat ;) Możesz się też bawić w pierwszy sposób, ale jak pisałem - to już trochę wyższy poziom i łatwo możesz gdzies walnąć błąd.

0

Chyba temat jest zbyt "prosty" do ogarnięcia, aby wkręcać się tak w niego :) Jestem bliski rozwiązania z sumą narastającą... może zaraz to rozpykam w "ludzki" sposób :)

0

Czyli co - robisz to w drugi z podanych przeze mnie sposobów, czy jeszcze coś innego wykminiłeś?

0

pomysł mam taki, aby wrzucić dodatkową kolumnę z sumą narastającą i jakoś włączyć w to funkcję COUNT, która zliczy ile jest wartości mniejszych od wskazanej przeze mnie wartości.

0

A czy robiąc zestawienie masz uwzględniać tylko bieżący miesiąc, czy całość od początku bazy?

0
PapaJapa napisał(a):

Chyba temat jest zbyt "prosty" do ogarnięcia, aby wkręcać się tak w niego :) Jestem bliski rozwiązania z sumą narastającą... może zaraz to rozpykam w "ludzki" sposób :)

A jak byś zrobił podzapytanie dla każdego klienta w którym wyliczysz sumę zysków klintów którzy są równi jego zyskowi i tym ponad nim to będziesz miał sumę rosnącą.

0
cerrato napisał(a):

A czy robiąc zestawienie masz uwzględniać tylko bieżący miesiąc, czy całość od początku bazy?

Analizuje zawsze bieżący miesiąc.

1
DECLARE @t1 TABLE
    (
        Id INT ,
        Sales MONEY
    );

INSERT INTO @t1
VALUES ( 1, 10000.00 ) ,
       ( 2, 110000.00 ) ,
       ( 3, 30000.00 ) ,
       ( 4, 21000.10 ) ,
       ( 5, 50000.43 ) ,
       ( 6, 20000.00 ) ,
       ( 7, 20000.07 ) ,
       ( 8, 20000.00 );

DECLARE @Sales MONEY;

SELECT @Sales = SUM(Sales) * 0.80
FROM   @t1;

SELECT SUM(Sales) [Sales100%] ,
       @Sales [Sales80%]
FROM   @t1;

SELECT *
FROM   (   SELECT a2.* ,
                  CASE WHEN LAG(@Sales - a2.Running_total) OVER ( ORDER BY a2.Sales DESC ) < 0 THEN
                           0
                       ELSE 1
                  END [Top80%_Contributor]
           FROM   (   SELECT Id ,
                             Sales ,
                             SUM(Sales) OVER ( ORDER BY Sales DESC ) Running_total
                      FROM   @t1 ) AS a2 ) AS a3
WHERE  a3.[Top80%_Contributor] = 1;

screenshot-20190304153620.png

1

Nie programiści mówią że 80% dochodu generuje 20% kontrahentów bez liczenia podobno tak jest :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1