大家好,我有一个很长的查询,我试图用更少的单词减少它并尝试优化它。
这是我的问题:
SET @year := 2013;
SET @euro := 3.14;
SELECT
SUM(IF (CONCAT(@year, '-01') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Jan,
SUM(IF (CONCAT(@year, '-02') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Feb,
SUM(IF (CONCAT(@year, '-03') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Mar,
SUM(IF (CONCAT(@year, '-04') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Apr,
SUM(IF (CONCAT(@year, '-05') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) May,
SUM(IF (CONCAT(@year, '-06') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Jun,
SUM(IF (CONCAT(@year, '-07') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Jul,
SUM(IF (CONCAT(@year, '-08') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Aug,
SUM(IF (CONCAT(@year, '-09') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Sep,
SUM(IF (CONCAT(@year, '-10') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Oct,
SUM(IF (CONCAT(@year, '-11') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Nov,
SUM(IF (CONCAT(@year, '-12') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) `Dec`
FROM insurances i
INNER JOIN policies p ON p.id = i.policy_id
WHERE (i.initial_date >= p.date_ini
AND i.final_date <= p.date_expired)
这是我的结果:
JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
20286 20286 26496 26496 26496 26496 26496 26496 9936 9936 9936 9936
以下是我的演示:http://sqlfiddle.com/#!2/074ff/1
请有人帮助我吗?
我真的很感激帮助。
答案 0 :(得分:2)
这是您的另一种选择。
由于@sqlvars的创建,这可能会持续一段时间,但它应该在几个方面有所帮助。
第一个FROM(创建sqlvars的子选择)除了创建12个表示每月Jan-Dec的“dt”日期的简单变量作为日期格式之外什么都不做,我们摆脱了每个字符串连接。记录日期和相应的起始日期。
第二个FROM(子选择仅查询有关日期范围的那些合格记录,但是当它在那里时,它会将@euro因子计算为最终列名“InsAmount”。
最后,合并在一起的那些简化了SUM()聚合可读性因子。
SET @euro := 3.14;
SELECT
SUM( IF ( @dtJan BETWEEN date_ini AND date_expired, InsAmount, 0)) Jan,
SUM( IF ( @dtFeb BETWEEN date_ini AND date_expired, InsAmount, 0)) Feb,
SUM( IF ( @dtMar BETWEEN date_ini AND date_expired, InsAmount, 0)) Mar,
SUM( IF ( @dtApr BETWEEN date_ini AND date_expired, InsAmount, 0)) Apr,
SUM( IF ( @dtMay BETWEEN date_ini AND date_expired, InsAmount, 0)) May,
SUM( IF ( @dtJun BETWEEN date_ini AND date_expired, InsAmount, 0)) Jun,
SUM( IF ( @dtJul BETWEEN date_ini AND date_expired, InsAmount, 0)) Jul,
SUM( IF ( @dtAug BETWEEN date_ini AND date_expired, InsAmount, 0)) Aug,
SUM( IF ( @dtSep BETWEEN date_ini AND date_expired, InsAmount, 0)) Sep,
SUM( IF ( @dtOct BETWEEN date_ini AND date_expired, InsAmount, 0)) Oct,
SUM( IF ( @dtNov BETWEEN date_ini AND date_expired, InsAmount, 0)) Nov,
SUM( IF ( @dtDec BETWEEN date_ini AND date_expired, InsAmount, 0)) `Dec`
from
( select
@dtJan := '2013-01-01',
@dtFeb := DATE_ADD( @dtJan, INTERVAL 1 MONTH ),
@dtMar := DATE_ADD( @dtFeb, INTERVAL 1 MONTH ),
@dtApr := DATE_ADD( @dtMar, INTERVAL 1 MONTH ),
@dtMay := DATE_ADD( @dtApr, INTERVAL 1 MONTH ),
@dtJun := DATE_ADD( @dtMay, INTERVAL 1 MONTH ),
@dtJul := DATE_ADD( @dtJun, INTERVAL 1 MONTH ),
@dtAug := DATE_ADD( @dtJul, INTERVAL 1 MONTH ),
@dtSep := DATE_ADD( @dtAug, INTERVAL 1 MONTH ),
@dtOct := DATE_ADD( @dtSep, INTERVAL 1 MONTH ),
@dtNov := DATE_ADD( @dtOct, INTERVAL 1 MONTH ),
@dtDec := DATE_ADD( @dtNov, INTERVAL 1 MONTH ) ) sqlvars,
( select
date_ini,
date_expired,
i.net_insurance * IF (type_money = 2, @euro, 1) as InsAmount
from
insurances i
INNER JOIN policies p ON i.policy_id = p.id
WHERE
i.initial_date >= p.date_ini
AND i.final_date <= p.date_expired ) as QryRecs
答案 1 :(得分:1)
您正在尝试进行数据透视查询,MySQL不支持。正如您所看到的,解决方法变得非常难看,非常快。
您唯一的选择是切换到支持PIVOT
查询的DBMS,或者在没有所有条件列逻辑的情况下恢复到传统的SELECT ... FROM ...
查询,并执行rows-&gt;列转换在您的客户端代码中。