2017-08-02 5 views
9

Ich habe eine column in einer SQL table. Das enthält eine date Lieferauftrag.Wie berechnet man den Umsatz pro Semester

Also das gleiche Datum wiederholen sein kann (an einem Tag delivred wir severals Aufträge), wie folgt aus:

05-01-16 
05-01-16 
05-01-16 
08-01-16 
08-01-16 
14-01-16 
22-01-16 
22-01-16 
04-02-16 
05-02-16 
05-02-16 

ich will, in each 6 months die AVG des Umsatzes jedes Artikels berechnen, erkläre ich mehr:

From January to June ==> Turnover 1 
From Febrary to July ==> Turnover 2 
From March to August ==> Turnover 3 
From April to September ==> Turnover 4 
From May to Obtober ==> Turnover 5 
From June to November ==> Turnover 6 
From July to December ==> Turnover 7 

ich extrahierte bereits den Monat durch die Anfrage unten, aber ich kann nicht dynamisch berechnen (weil meine Daten jeden Monat geändert werden sollen), um den Umsatz wie in diesem Beispiel oben:

select distinct extract (month from Article) as mt 
order by mt 

Ich habe versucht, eine cursor zu verwenden, aber ich kann nicht zur besten Lösung kommen.

habe ich eine Anfrage einen Umsatz pro Artikel für jeden Kunden zu berechnen, in the first 6 months (ich habe es manuell) ist die folgende:

select "LRU", "Client", round(sum("Montant_fac_eur")) 
from "foundry" 
where "Nature"='Repair' 
and "Client"={{w_widget3.selectedValue}} 
and "annee"='2016' 
and extract (month from "date") between '1' and '6' 


group by "LRU", "Client" 

Ihr Ergebnis ist die folgende:

LRU   Client round 
"article1"  4001 8859  Turnover of article1 from January to June 
"article2"  4001 94315 Turnover of article2 from January to June 
"article3"  4001 273487 Turnover of article3 from January to June 
"article4"  4001 22292 Turnover of article4 from January to June 
"article5"  4001 22292 Turnover of article5 from January to June 
"article6"  4001 42590 Turnover of article6 from January to June 
"article7"  4001 9965  Turnover of article7 from January to June 
"article8"  4001 39654 Turnover of article8 from January to June 
"article9"  4001 3883  Turnover of article9 from January to June 
"article10"  4001 41612 Turnover of article10 from January to June 

I Wollen Sie eine Schleife machen, um einen Umsatz alle 6 Monate zu berechnen, ohne es manuell zu schreiben, wenn es möglich ist? Kann jemand mir bitte helfen und mir eine Lösung oder einen Vorschlag geben, wie kann ich es tun? Danke.

+2

könnten Sie bitte Abtastwerteingang und erwartete Ausgabe posten? –

+0

Ich habe meine Frage oben geändert. Vielen Dank. – vero

+0

wäre es sehr nützlich, das Schema der "Gießerei" -Tabelle ohne sensible Daten zu erhalten. Z.B. Ändern Sie die Spaltennamen. –

Antwort

6

Hier können Sie die vereinfachte Definition und Lösung des Problems sehen (wenn ich Sie richtig verstanden habe): http://sqlfiddle.com/#!9/48a2e1/1

CREATE TABLE foundry 
(
    lru varchar(50) NOT NULL, 
    client int NOT NULL, 
    purchase_date date, 
    price int NOT NULL 
); 

INSERT INTO foundry (lru, client, purchase_date, price) VALUES 
("article1", 4001, "01-01-16", 100), 
("article1", 4001, "01-01-17", 200), 
("article1", 4001, "01-02-16", 300), 
("article1", 4001, "01-04-16", 400), 
("article1", 4001, "01-06-16", 500), 
("article1", 4001, "01-08-16", 600), 
("article1", 4001, "01-10-16", 700), 
("article1", 4001, "01-11-16", 800), 
("article1", 4002, "01-01-16", 900), 
("article1", 4002, "01-07-16", 1000), 
("article1", 4002, "01-12-16", 1100); 

Grundsätzlich haben wir eine Tabelle mit vier Spalten: lru (Artikelname), Kunde, Kaufdatum und etwas Preis.

Die Lösung sieht so aus:

SELECT lru, client, avg(price), COUNT(*) as total_items, 
MONTHNAME(STR_TO_DATE(L, '%m')) as start_month, MONTHNAME(STR_TO_DATE(R, '%m')) as end_month FROM foundry, 
(
    SELECT 1 as L, 6 as R 
    UNION ALL 
    SELECT 2, 7 
    UNION ALL 
    SELECT 3, 8 
    UNION ALL 
    SELECT 4, 9 
    UNION ALL 
    SELECT 5, 10 
    UNION ALL 
    SELECT 6, 11 
    UNION ALL 
    SELECT 7, 12 
) months 
WHERE month(purchase_date) >= L AND month(purchase_date) <= R 
GROUP BY lru, client, L, R 

Die Idee ist:

  1. generieren alle möglichen Kombinationen der Monate: 1-6, 2-7, ..., 7,12
  2. Registriert Quelldaten mit generierten Monate Kombination
  3. Verwenden AVG mit GROUP BY

Und das Ergebnis:

lru  client avg(price) total_items  start_month  end_month 
article1 4001 300  5 January  June 
article1 4001 400  3 February July 
article1 4001 500  3 March August 
article1 4001 500  3 April September 
article1 4001 600  3 May  October 
article1 4001 650  4 June November 
article1 4001 700  3 July December 
article1 4002 900  1 January  June 
article1 4002 1000 1 February July 
article1 4002 1000 1 March August 
article1 4002 1000 1 April September 
article1 4002 1000 1 May  October 
article1 4002 1000 1 June November 
article1 4002 1050 2 July December 
+0

Was ist mit 6-Monats-Intervallen, die in der zweiten Hälfte des Jahres beginnen, z. 8-1 (nächstes Jahr)? – miazo

+0

Dann sollten wir die Abfrage mit UNION ALL verbessern. Außerdem sollten wir das Jahr berücksichtigen. So konnten wir mögliche Kombinationen von Monaten und Jahren generieren. {generated_month_combinations} beitreten {possible_years} –

+0

Gute Antwort tvelkyy danke, dass du dir die Zeit genommen hast, es zu erklären. – Rob212

2

Ich würde gemeinsame Tabellenausdrücke für jede sechsmonatige Abdeckung empfehlen. https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx Like: mit tp1 (Turnoverperiod, Averagevaule) als ( wählen 'Period1' als Turnoverperiod, AVG (Umsatz) als AverageValue wo Datum zwischen period1.startdate und period2.enddate) , tp2 als ( .... tp2 )

select * from tp1 Vereinigung select * from tp2

Sie können auch eine dynamische SQL-Zeichenfolge erstellen (nvarchar (max)) Sie können die Union-Abfragen programmatisch anhängen und dann sp_executesql-Anweisung verwenden.

+0

'Periode', 'Periode1' und 'Periode2' sind die Spalten? weil meine Spalte das Datum ihrer Struktur wie im obigen Beispiel enthält, so sollte ich in diesem Fall die Periode manuell schreiben. – vero

2

Ich bin nicht sicher, welche RDBMS Sie verwenden, so ist hier eine mögliche Lösung mit ANSI SQL (RDBMS analog verwenden)

Try-Adresse dieses Problem in zwei Schritten:

  1. Erstellen Sie eine Ansicht in einer Form (können Sie sagen es v_turnover_per_month nennen), unter Verwendung von basischen Gruppe durch Syntax über Ihre Quelltabelle:

    article month turnover 
    art1  201701 1000 
    art1  201702 1020 
    ...  ...  ... 
    art2  201701 5000 
    ...  ...  ... 
    
  2. verwenden folgende select-Anweisung

    SELECT article, 
         'Turnover from ' || m1.month || ' until ' || m6.month as title, 
         max(m1.turnover + m2.turnover + m3.turnover + m4.turnover + m5.turnover + m6.turnover) as total_turnover_6month 
    
    FROM v_turnover_per_month as m6 
    JOIN v_turnover_per_month as m5 ON m6.article = m5.article and m5.month+1=m6.month 
    JOIN v_turnover_per_month as m4 ON m6.article = m4.article and m4.month+1=m5.month 
    JOIN v_turnover_per_month as m3 ON m6.article = m3.article and m3.month+1=m4.month 
    JOIN v_turnover_per_month as m2 ON m6.article = m2.article and m2.month+1=m3.month 
    JOIN v_turnover_per_month as m1 ON m6.article = m1.article and m1.month+1=m2.month 
    
    GROUP BY 1, 2; 
    
+0

OP verwendet mysql –

2

Hier ist mein nehmen:

DROP TABLE IF EXISTS test; 

# credit to tvelykyy for providing some test data and table def which I adapted 
CREATE TABLE test (lru VARCHAR(16), `client` INTEGER UNSIGNED, purchase_date DATE, price int NOT NULL); 

INSERT INTO test (lru, client, purchase_date, price) VALUES 
("article1", 4001, '2016-01-01', 100), 
("article1", 4001, '2016-02-01', 200), 
("article1", 4001, '2016-03-01', 300), 
("article1", 4001, '2016-04-01', 400), 
("article1", 4001, '2016-05-01', 500), 
("article1", 4001, '2016-06-01', 600), 
("article1", 4001, '2016-07-01', 700), 
("article1", 4001, '2016-08-01', 800), 
("article1", 4002, '2016-01-01', 1100), 
("article1", 4002, '2016-06-01', 1200); 

SELECT A.lru, A.`client`, ROUND(SUM(price)) round, CONCAT('Turnover of article ', A.lru, ' from ', DATE_FORMAT(DATE_ADD(MAX(B.purchase_date), INTERVAL -6 MONTH), '%M %Y'), ' to ', DATE_FORMAT(MAX(B.purchase_date), '%M %Y')) period FROM 
    (
    SELECT DISTINCT lru, LAST_DAY(purchase_date) purchase_month, `client` FROM test 
) A 
LEFT OUTER JOIN 
    test B 
ON A.lru = B.lru AND A.`client` = B.`client` AND A.purchase_month >= LAST_DAY(B.purchase_date) AND DATE_ADD(A.purchase_month, INTERVAL -6 MONTH) < LAST_DAY(B.purchase_date) 
GROUP BY A.lru, A.`client`, A.purchase_month 
ORDER BY A.lru, A.`client`, A.purchase_month; 

Die Abfrage durch Auswahl der DISTINCT lru, Kunden und Monate in der Unterabfrage A arbeitet, die eine LEFT JOIN zurück zu den ursprünglichen Daten ermöglicht ON LR, Kunde und Datum in den letzten sechs Monaten, wobei der letzte Tag jedes Monats verwendet wird, um die Monate in einer standardisierten Weise zu definieren. Schließlich wird die Aggregation wie angegeben verwendet.

Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen oder ich die Frage in ihrer Gesamtheit nicht verstanden habe.

Danke,

James

Verwandte Themen