2017-02-05 4 views
0

Ich habe die drei höchsten Ausgaben Kunden von Customer (Kundennamen, id) und order (Bestell-ID, um amt, Bestelldatum) für jede Woche zu finden. Wenn ich die Abfrage heute ausführe, sollte sie die obersten 3 für alle Wochen anzeigen, für die das Bestelldatum existiert.Wie partitionieren Sie Ergebnisse wöchentlich in SQL?

Ich denke an ein Partition by über das Datum (wöchentlich) zu tun, aber ich kann keine Methode finden, das zu tun? Hat jemand eine wöchentliche Aufteilung der Ergebnisse vorgenommen?

Ich weiß, es ist nicht richtig, aber das ist, was ich habe:

Select Top 3 customer_name, id OVER (partition by [week]) 
(
    Select c.customer_name, c.id, o.order_amt, 
    from customer c 
    Join Order o 
     on c.id=o.id 
    group by c.id 
) 
+2

eine Datenbank Auswahl: 'mysql = SQL-server' und für diese Frage eine Antwort auf eine könnte zu einer Antwort signifikant unterschiedlich sein das andere. –

Antwort

1

Nach Ihrer Tabellenstruktur sein sollte, wo orders.order_id ist customer.id Einsatz diese Aussage

select 
    * 
from 
(
    select 
     details.* 
     ,dense_rank() over (partition by week_num order by order_amt desc) as rank_num 
    from 
    (
     select 
      c.id as customer_id 
      ,c.name 
      ,sum(o.order_amt) as order_amt 
      ,datepart(WEEK,o.order_date) as week_num  
     from customer c 
     join orders o on c.id=o.order_id 
     group by c.id,c.name,datepart(WEEK,o.order_date) 
    )details 

)dets 
where dets.rank_num<=3 

Aktualisiert: chan ged Anweisung nur 2 Tabellen verwenden

+0

Danke! obwohl es nur 2 Tabellen gab und ID war cust id, die in beiden Kunden n Reihenfolge Tabelle ist. Aber warum wird der Erste mit dichtem Rang außerhalb der Unterabfrage ausgewählt? Kann es nicht 1 Anfrage sein? –

+0

Ich habe die Abfrage aktualisiert, damit sie mit Ihrer Tabellenstruktur übereinstimmt. – Lemjur

+0

'Dense_rank()' kann in die erste Unterabfrage gestellt werden, aber die Anweisung wäre weniger lesbar wegen der Zeile ', desse_rank() over (Partition nach Datumsteil (WEEK, o.order_date) order by sum (o.order_amt) desc) als rank_num' – Lemjur

0

die Abfrage so etwas wie diese

Select customer_name, id, order_amt, [week] 
(
    Select c.customer_name, c.id, o.order_amt, [week], 
      rn = row_number() over (partition by [week] order by o.order_amt desc) 
    from customer c 
    Join Order o 
     on c.id=o.id 
) d 
where rn <= 3 
+0

Danke! Aber wird es automatisch in Wochen mit "Partition bis [Woche]" aufgeteilt oder muss ich andere Bedingungen hinzufügen oder Startdatum/Bestelldatum? Ist die Syntax korrekt? –

+0

Warum versuchen Sie, 2 verschiedene Sammlungen nach "Kunden-ID" zu verbinden, die unterschiedliche IDs zu sein scheinen? Speichert 'order_id'' customer_id' Informationen? – Lemjur

+0

Ist das eine bessere Antwort? Ihre Antwort auf Partition nach Datumsteil (Woche, o.Orderdatum) wurde geändert. Select customer_name, id, Order_Amt ( Select c.customer_name, c.id, o.order_amt, row_number() über (Partition von Datumsteil (Woche, o.order_date), um von o.order_amt ab) als rn von Kunde c Join Order o auf c.id = o.id Gruppe von c.id ) d wo rn <= 3 –

0

dies ist eine Idee,

;WITH CTE 
AS (
    SELECT c.customer_name 
     ,c.id 
     ,o.order_amt 
     ,datepart(wk, datecol) AS Weekcol 
    ) 
    ,CTE1 
AS (
    SELECT c.customer_name 
     ,c.id 
     ,o.order_amt 
     ,ROW_NUMBER() OVER (
      PARTITION BY Weekcol ORDER BY order_amt DESC 
      ) AS rowNUm 
    FROM CTE 
    ) 
SELECT * 
FROM CTE1 
WHERE rowNUm <= 3 
+0

Was ist, wenn 2 Kunden die gleiche Anzahl von Bestellungen haben? 'Dense_rank()' ist besser als 'Row_num()'. Zweites Problem ist die mehrfache Tätigkeit der Kunden. Er kann mehr als eine Operation pro Tag durchführen, also muss eine Aggregation auf 'order_amt' erfolgen. – Lemjur