在mySQL中压缩SQL

时间:2009-06-11 09:00:46

标签: sql mysql refactoring complexity-theory

如何在MySQL中简化此代码?

SELECT name,
  MAX(IF(to_days(thedate) - to_days('2009-06-13') = 0, price, '')) AS date1,
  MAX(IF(to_days(thedate) - to_days('2009-06-13') = 1, price, '')) AS date2,
  MAX(IF(to_days(thedate) - to_days('2009-06-13') = 2, price, '')) AS date3,
  MAX(IF(to_days(thedate) - to_days('2009-06-13') = 3, price, '')) AS date4,
  MAX(IF(to_days(thedate) - to_days('2009-06-13') = 4, price, '')) AS date5,
  MAX(IF(to_days(thedate) - to_days('2009-06-13') = 5, price, '')) AS date6,
  MAX(IF(to_days(thedate) - to_days('2009-06-13') = 6, price, '')) AS date7,
AVG(price),SUM(price)
FROM `personals`
WHERE personal_id = '1234'
GROUP BY name

这样计算的日期数是动态的吗?

3 个答案:

答案 0 :(得分:1)

最有效的方法是将其拆分为两个查询,一个用于加载平均价格和每人价格总和:

SELECT
  AVG(price), SUM(price)
FROM `personals`
WHERE personal_id = '1234'
GROUP BY name;

和第二个你想知道的最大值:

SELECT
  MAX(price)
FROM `personals`
WHERE personal_id = '1234'
GROUP BY name, to_days(thedate) - to_days('2009-06-13');

如果您确实希望列在同一个查询中,请使用第一个子查询(在大型数据库上可能效率不高)

SELECT
  MAX(price),
  AVG(price),
  SUM(price)
FROM `personals`
LEFT JOIN (
  SELECT
    AVG(price), SUM(price), name
  FROM `personals`
  WHERE personal_id = '1234' -- # this line is optional
  GROUP BY name
) totals
ON totals.name = personals.name
WHERE personal_id = '1234'
GROUP BY name, to_days(thedate) - to_days('2009-06-13');

答案 1 :(得分:0)

您无法动态更改列数,但可以非常轻松地为每个日期获取单独的行:

SELECT to_days(thedate) - to_days('2009-06-13') as interval,
   max(price) FROM `personals`
WHERE personal_id = '1234'
GROUP BY name, thedate

您需要执行单独的查询才能获得平均数据:

SELECT name,
   AVG(price),SUM(price)
FROM `personals`
WHERE personal_id = '1234'
GROUP BY name

答案 2 :(得分:0)

如果我正确理解你,那么我认为你不能做你想做的事情:SQL不会这样做。如果您的查询是从其他程序使用的,并且您知道您感兴趣的日期计数集,那么您可以在提交之前将其构建为字符串。如果你想要所有可能的天数并且必须有一个SQL查询,那么我想,UNION会这样做(虽然我更喜欢两个查询):

SELECT
  name
, to_days(thedate) - to_days('2009-06-13') AS num_days
, MAX(price) As max_price
, NULL AS avg_price
, NULL AS sum_price
FROM `personals`
WHERE personal_id = '1234'
GROUP BY
  name
, to_days(thedate) - to_days('2009-06-13') 
UNION ALL
SELECT
  name
, NULL
, NULL
, AVG(price)
, SUM(price)
FROM `personals`
WHERE personal_id = '1234'
GROUP BY name