开发者

Slow running query, is there a better way?

I've got a query that produces the right result, its just very slow. I feel like there must be a better way (perhaps without subqueries).

Table, result and query are below. I've anonymized the data and I have 8 subqueries rather than 2, but the format is the same.

Table "a":

开发者_开发问答id      userId       type     amount
------------------------------------
 1      1            a        400
 2      1            b        300
 3      1            c        230
 4      2            a        600
 5      2            b        500
 6      2            c        430

I've got an index on each column and one additional one that encompasses the userId and type columns. I can also guarantee you that userId and type are unique (i.e. there would't be two type 'a' for user 1).

Desired Result:

userId   typeAtotal  typeBtotal
--------------------------------
  1      400         300
  2      600         500

My Query:

SELECT userId, 
       (SELECT amount 
          FROM a AS a2 
         WHERE a2.userId = a1.userId 
           AND a2.type = 'a') AS aAmt,
       (SELECT amount 
          FROM a AS a3 
         WHERE a3.userId = a1.userId 
           AND a3.type = 'b') AS bAmt
    FROM a AS a1 
   WHERE type IN ('a','b') 
GROUP BY userId


Use:

  SELECT t.userid,
         MAX(CASE WHEN t.type = 'a' THEN amount ELSE NULL END) AS typeAtotal,
         MAX(CASE WHEN t.type = 'b' THEN amount ELSE NULL END) AS typeBtotal
    FROM YOUR_TABLE t
GROUP BY t.userid

If there can be more than one amount for either type - this will return the highest. If you want such situations added, use SUM:

  SELECT t.userid,
         SUM(CASE WHEN t.type = 'a' THEN amount ELSE NULL END) AS typeAtotal,
         SUM(CASE WHEN t.type = 'b' THEN amount ELSE NULL END) AS typeBtotal
    FROM YOUR_TABLE t
GROUP BY t.userid


Looks like cross-tabulation to me. You might try something like this:

SELECT userId, 
    SUM(IF(a.type = 'a'), a.amount, 0) AS aAmount, 
    SUM(IF(a.type = 'b'), a.amount, 0) AS bAmount
FROM a
WHERE type IN ('a', 'b')
GROUP BY a.userId

You might want to read this rather well-written tutorial: http://dev.mysql.com/tech-resources/articles/wizard/index.html

Edit: fixed the ELSE condition.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜