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 ? :)
Źle zdefiniowane zadanie.
@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
Kurde no znęcacie się tak z poniedziałku :) Oczywiście, że chodzi o największych. To o zasadę Pareto się ociera.
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.
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.
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.
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 :)
Czyli co - robisz to w drugi z podanych przeze mnie sposobów, czy jeszcze coś innego wykminiłeś?
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.
A czy robiąc zestawienie masz uwzględniać tylko bieżący miesiąc, czy całość od początku bazy?
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ą.
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.
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;
Nie programiści mówią że 80% dochodu generuje 20% kontrahentów bez liczenia podobno tak jest :)