1

I've been trying for hours but can't get the query to do what I want using DB2. From table Company and Users I have the following tickets quantity info per company/user

user         company      quantity
------------ ------------ ------------
mark         nissan       300
tom          toyota       50
steve        krysler      80
mark         ford         20
tom          toyota       120
jose         toyota       230
tom          nissan       145
steve        toyota       10
jose         krysler      35
steve        ford         100

This is generated by the query:

SELECT T.USER, COUNT(T.USER) AS QUANTITY, T.COMPANY FROM TICKET T
INNER JOIN COMPANY P ON P.COMPANY = T.COMPANY 
GROUP BY (T.USER, T.COMPANY) -- ORDER BY QUANTITY DESC

What I want to see is the top user for each company, so given the data above, the query should show me:

user         company      quantity (Top user per company)
------------ ------------ --------------------------------
mark         nissan       300
jose         toyota       230
steve        ford         100
steve        krysler      80

How can I write the SQL to return this result?


Final answer (noted in a comment):

SELECT user, quantity, company
  FROM (SELECT user, quantity, company,
               RANK () OVER (PARTITION BY company ORDER BY quantity DESC) AS r
          FROM (SELECT T.USER, COUNT(T.USER) AS QUANTITY, T.COMPANY
                  FROM TICKET T JOIN COMPANY P ON P.COMPANY = T.COMPANY
                 GROUP BY (T.USER, T.COMPANY) ) s ) t
 WHERE r = 1;
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278

2 Answers2

2

Build it up step by step.

Find the maximum quantity for each company, assuming the first data table shown in the question is called 'Tickets':

SELECT Company, MAX(Quantity) AS MaxQuantity
  FROM Tickets
 GROUP BY Company;

Now, find the data for the user(s) with that maximum quantity for that company:

SELECT T.User, T.Company, M.MaxQuantity
  FROM Tickets AS T
  JOIN (SELECT Company, MAX(Quantity) AS MaxQuantity
          FROM Tickets
         GROUP BY Company) AS M
    ON T.Company = M.Company AND T.Quantity = M.MaxQuantity;

If the top quantity for a particular company was, say, 200 and two users both scored 200 for that company, then this query lists both users.

Now, if you mean that the query you show in the question generates the first result table, then what I called tickets just above needs to be the derived table:

SELECT T.User, COUNT(T.User) AS Quantity, T.Ccompany
  FROM Ticket AS T
 INNER JOIN Company AS P ON P.Company = T.Company 
 GROUP BY (T.User, T.Company)
 ORDER BY QUANTITY DESC 

In which case, we can use a WITH clause (syntax unchecked, but I think it is correct per SQL standard):

WITH Tickets AS
    (SELECT T.User, COUNT(T.User) AS Quantity, T.Ccompany
       FROM Ticket AS T
       JOIN Company AS P ON P.Company = T.Company 
      GROUP BY (T.User, T.Company)
    )
SELECT T.User, T.Company, M.MaxQuantity
  FROM Tickets AS T
  JOIN (SELECT Company, MAX(Quantity) AS MaxQuantity
          FROM Tickets
         GROUP BY Company) AS M
    ON T.Company = M.Company AND T.Quantity = M.MaxQuantity;

Clearly, you can also write the WITH sub-query out twice if you prefer.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • +1 Nice I didn't know DB2 supported [WITH](http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp?topic=/com.ibm.db2.luw.apdv.java.doc/doc/rjvsjwth.html) – Conrad Frix Jun 15 '11 at 16:25
1

This should work. Create a derived view to calculate the Quantity per user and per company. Then get the max of then Quantity and then join the max back to the the calculation of the quantity.

SELECT p.company, 
       t.user, 
       t.quantity 
FROM   (SELECT MAX(t.quantity) max_quantity, 
               t.company 
        FROM   (SELECT  
                       COUNT(t.user) quantity, 
                       t.company 
                FROM   ticket t 
                GROUP  BY t.company) t) maxq 
       INNER JOIN (SELECT t.user, 
                          t.company, 
                          COUNT(t.user) quantity 
                   FROM   ticket t 
                   GROUP  BY t.company, 
                             t.user) t 
         ON maxq.max_quantity = t.quantity 
            AND maxq.company = t.company 
       INNER JOIN company p 
         ON p.company = t.company 
ORDER  BY t.quantity DESC 

A working sample that shows the top users by tag for the StackOverflow data can be found here.

Community
  • 1
  • 1
Conrad Frix
  • 51,984
  • 12
  • 96
  • 155
  • Hey, thanks for your answear but I don't need the top 10 of all the result, I need the TOP(1) user group by company, i.e. in toyota there are many users, it should show me which user has the most quantity, in this case would be Jose because he has 230. The same logic for the other companies. – Juan Carlos Costilla Jun 13 '11 at 17:30
  • hi thanks for your help, now this query you sent me gave me some errors, changing some variables it gave the the TOP USER but in General, not grouped by as i wanted. I hope you can keep helping me as this is very important, what i need is the top user BY COMPANY that is GROUP BY... THANK YOU – Juan Carlos Costilla Jun 13 '11 at 21:16
  • @Juan I'm sorry you encountered errors. I had an extra `t.user` in the query. I've removed it but if this doesn't help you'll need to let me know what the error are. – Conrad Frix Jun 13 '11 at 21:36
  • hey @Conrad your query is giving the top users by company? or the top user in general? – Juan Carlos Costilla Jun 13 '11 at 21:38
  • this is the query that gave me no errors : SELECT p.company, t.user, t.quantity FROM (SELECT MAX(quantity) as max_quantity FROM (SELECT t.user, COUNT(t.user) quantity, t.company FROM ticket t GROUP BY t.company, t.user)) maxq INNER JOIN (SELECT t.user, COUNT(t.user) quantity, t.company FROM ticket t GROUP BY t.company, t.user) t ON maxq.max_quantity = t.quantity INNER JOIN company p ON p.company = t.company ORDER BY t.quantity DESC – Juan Carlos Costilla Jun 13 '11 at 21:43
  • but only gave me the TOP USER in GENERAL (in all companies) but I need in each company who is the highest – Juan Carlos Costilla Jun 13 '11 at 21:44
  • @Juan In the maxq you've dropped `t.company` from the `SELECT` and `GROUP BY` clauses int maxQ which is why you're only getting the top overall and not by Company. Try adding them back – Conrad Frix Jun 13 '11 at 21:47
  • @Juan also you need to remember to include `AND maxq.company = t.company` in the join – Conrad Frix Jun 13 '11 at 21:48
  • it gives me this error : SQL0119N An expression starting with "COMPANY " specified in a SELECT clause, HAVING clause, or ORDER BY clause is not specified in the GROUP BY clause or it is in a SELECT clause, HAVING clause, or ORDER BY clause with a column function and no GROUP BY clause is specified. – Juan Carlos Costilla Jun 13 '11 at 22:10
  • @Juan looks like you forgot to include COMPANY in a GROUP BY clause – Conrad Frix Jun 13 '11 at 22:44
  • Final answear ! SELECT user, quantity, company FROM ( SELECT user, quantity, company , RANK () OVER (PARTITION BY company ORDER BY quantity DESC) as r FROM ( SELECT T.USER, COUNT(T.USER) AS QUANTITY, T.COMPANY FROM TICKET T JOIN COMPANY P ON P.COMPANY = T.COMPANY GROUP BY (T.USER, T.COMPANY) ) s ) t WHERE r = 1 – Juan Carlos Costilla Jun 13 '11 at 22:54
  • hey @Conrad thanks a lot for your help, i also tried to include it in the gorup by but company is in every group by clause, well that's a correct answear i got in other post. thanks a lot for your help – Juan Carlos Costilla Jun 13 '11 at 22:55