Question

I try to make a query, so that I can see who is the top customer in a month (every month since begin till now).

Now I have the tables:

orders (orderID, orderdate, customerID, Netamount, tax, totalamount)

orderline (orderlineID, orderID, prodID, quantity, orderdate)

customer (firstname lastname zip creditcardtype etc.)

I think the other tables aren't necessarily here.

Of course there are customers who never bought a thing and customers who already bought plenty of times.

Now I used this query:

    SELECT customerid, Sum(netamount) 
    FROM orders
    GROUP BY customerid limit 1000000;

Now I see all customers who already bought sth. with the total amount they paid.

With the query

    SELECT YEAR ( Orderdate ) Year ,
    MONTHNAME ( Orderdate ) Month ,
    COUNT(*) TotOrd ,
    FROM orders
    GROUP BY YEAR ( Orderdate ),
    MONTH ( Orderdate );

I get a table where each row shows me the Year Month Total order (placed in that month).

Still I want just to see the Top Customer of a month.

I searched a lot in the internet still couldn't find that what I want (maybe I just googled wrong). I know that I need at least one inline view still no idea how to realize it.

Hope someone can help me out here.

Was it helpful?

Solution

You need to join back to the data to get the top customer. So, first calculate the maximum amount in each month, then join back to get the customer with that amount:

select my.year, my.month, myc.customerid, myc.totord
from (select year, month, max(totord) as maxtotord
      from (SELECT YEAR ( Orderdate ) Year, MONTHNAME ( Orderdate ) Month, customerid, COUNT(*) TotOrd ,
            FROM orders
            GROUP BY YEAR ( Orderdate ), MONTH ( Orderdate ), customerid
           ) myc
      group by year, month
     ) my join
     (SELECT YEAR ( Orderdate ) Year, MONTHNAME ( Orderdate ) Month, customerid, COUNT(*) TotOrd ,
      FROM orders
      GROUP BY YEAR ( Orderdate ), MONTH ( Orderdate ), customerid, count(*) as totord
     ) myc
     on my.year = myc.year and my.month = myc.month and my.maxtotord = myc.totord

Note that this is untested, so there might be a syntax error.

Also, this returns multiple customers if there are multiple customers with the max value.

Finally, this is much easier in almost any other database, because most databases now support the row_number() function.

OTHER TIPS

It's a group-wise max problem but unfortunately MySQL doesn't support window functions or CTE so this can be messy.

SELECT s1.year,s1.month,s1.customerid,s1.totord FROM
(SELECT YEAR ( Orderdate ) Year ,
MONTHNAME ( Orderdate ) Month , 
customerid,
COUNT(*) TotOrd 
FROM orders
GROUP BY YEAR ( Orderdate ),
MONTH ( Orderdate ),customerid) as s1
LEFT JOIN
(SELECT YEAR ( Orderdate ) Year ,
MONTHNAME ( Orderdate ) Month , 
customerid,
COUNT(*) TotOrd 
FROM orders
GROUP BY YEAR ( Orderdate ),
MONTH ( Orderdate ),customerid) as s2
ON
s1.year=s2.year AND s1.month=s2.month AND s2.TorOrd>s1.TotOrd AND s1.customerid>s2.customerid
WHERE s2.customerid IS NULL;

In case of doubles it will return the customer with lower id.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top