我有一个查询用于获取各种输入来计算资产排名。为了获得基于用户输入计算资产等级的各种值,我使用多个子查询到单个表。但这花费了太多时间。任何人都可以帮我改进这个查询吗?
SELECT AssetId,
AssetName,
Isin,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 12 MONTH
ORDER BY DDate ASC LIMIT 1) AS rafval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 12 MONTH
ORDER BY DDate DESC LIMIT 1) AS ralval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 3 MONTH
ORDER BY DDate ASC LIMIT 1) AS rbfval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 3 MONTH
ORDER BY DDate DESC LIMIT 1) AS rblval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 20 DAY
ORDER BY DDate ASC LIMIT 1) AS rcfval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 20 DAY
ORDER BY DDate DESC LIMIT 1) AS rclval,
(SELECT STD(DClose)
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 20 DAY
ORDER BY DDate DESC LIMIT 1) AS vstd
FROM assets a
INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
WHERE asg.AssetGroupId=1
AND a.IsActive=1;
在上面的查询中,子查询中提到的所有区间都是变量。它们来自用户输入。包含1000个资产的资产表和eod_data将包含数百万条记录。
我也为涉及where子句的所有字段创建了索引。
表格结构 assets:AssetId,AssetName,Isin,IsActive | eod_data:Isin,DClose,DDate
上述查询大约需要11分钟。
提前致谢。
请在此处找到示例数据库http://sqlfiddle.com/#!9/d0a50/3
答案 0 :(得分:1)
你可以试试这个查询吗?它只对所有列使用一个Join,但是对于您的示例数据,最后一个字段每次都为null,也与您的查询一致。
SELECT
AssetId
, AssetName
, a.Isin
, min(IF(DDate >= now()-interval 12 MONTH, DClose,null) ) AS rafval
, max(IF(DDate >= now()-interval 12 MONTH, DClose,null) ) AS ralval
, min(IF(DDate >= now()-interval 3 MONTH, DClose,null) ) AS rbfval
, max(IF(DDate >= now()-interval 3 MONTH, DClose,null) ) AS rblval
, min(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS rcfval
, max(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS rclval
, STD(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS vstd
FROM assets a
INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
LEFT JOIN eod_data ed ON ed.Isin = a.Isin
WHERE asg.AssetGroupId=1
AND a.IsActive=1
GROUP BY AssetId;
<强>样品强>
MariaDB [test]> SELECT
-> AssetId
-> , AssetName
-> , a.Isin
-> , min(IF(DDate >= now()-interval 12 MONTH, DClose,null) ) AS rafval
-> , max(IF(DDate >= now()-interval 12 MONTH, DClose,null) ) AS ralval
-> , min(IF(DDate >= now()-interval 3 MONTH, DClose,null) ) AS rbfval
-> , max(IF(DDate >= now()-interval 3 MONTH, DClose,null) ) AS rblval
-> , min(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS rcfval
-> , max(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS rclval
-> , STD(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS vstd
-> FROM assets a
-> INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
-> INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
-> LEFT JOIN eod_data ed ON ed.Isin = a.Isin
->
-> WHERE asg.AssetGroupId=1
-> AND a.IsActive=1
-> GROUP BY AssetId;
+---------+---------------------+---------+----------+----------+----------+----------+--------+--------+------+
| AssetId | AssetName | Isin | rafval | ralval | rbfval | rblval | rcfval | rclval | vstd |
+---------+---------------------+---------+----------+----------+----------+----------+--------+--------+------+
| 1 | AT ANDRITZ | ANDR_AT | 97.5700 | 97.5700 | 97.5700 | 97.5700 | NULL | NULL | NULL |
| 5 | AT BWT | BWTV_AT | 98.2000 | 98.2000 | 98.2000 | 98.2000 | NULL | NULL | NULL |
| 6 | AT ERSTE GROUP BANK | ERST_AT | 99.8000 | 99.8000 | 99.8000 | 99.8000 | NULL | NULL | NULL |
| 7 | AT EVN | EVNV_AT | 99.2600 | 99.2600 | 99.2600 | 99.2600 | NULL | NULL | NULL |
| 8 | AT FLUGHAFEN WIEN | VIEV_AT | 102.5200 | 102.5200 | 102.5200 | 102.5200 | NULL | NULL | NULL |
| 10 | AT IMMOFINANZ | IMFI_AT | 104.1600 | 104.1600 | 104.1600 | 104.1600 | NULL | NULL | NULL |
| 11 | AT LENZING | LENV_AT | 103.1300 | 103.1300 | 103.1300 | 103.1300 | NULL | NULL | NULL |
| 12 | AT MAYR MELNHOF | MMKV_AT | 104.3700 | 104.3700 | 104.3700 | 104.3700 | NULL | NULL | NULL |
| 13 | AT MEINL EUR LAND | MELV_AT | 103.0300 | 103.0300 | 103.0300 | 103.0300 | NULL | NULL | NULL |
| 14 | AT OMV | OMVV_AT | 102.7200 | 102.7200 | 102.7200 | 102.7200 | NULL | NULL | NULL |
| 15 | AT PALFINGER | PALF_AT | 101.2000 | 101.2000 | 101.2000 | 101.2000 | NULL | NULL | NULL |
| 17 | AT RHI AG | RHIV_AT | 98.7800 | 98.7800 | 98.7800 | 98.7800 | NULL | NULL | NULL |
| 18 | AT SCHOELLER-BLECK | SBOE_AT | 98.2100 | 98.2100 | 98.2100 | 98.2100 | NULL | NULL | NULL |
| 19 | AT SEMPERIT HDG | SMPV_AT | 98.4500 | 98.4500 | 98.4500 | 98.4500 | NULL | NULL | NULL |
| 20 | AT TELEKOM AUSTRIA | TELA_AT | 97.7400 | 97.7400 | 97.7400 | 97.7400 | NULL | NULL | NULL |
+---------+---------------------+---------+----------+----------+----------+----------+--------+--------+------+
15 rows in set (0.00 sec)
MariaDB [test]>
答案 1 :(得分:1)
这是我的下一次尝试。我测试了一些不同的连接。这是快速的方式(快1400倍)。 STD()列暂时未实现。可以请检查其他输出是否正确
..和STD决赛(我希望)。
SELECT
a.AssetId
, a.AssetName
, a.Isin
, CAST(COALESCE(ed2.DClose,0) AS DECIMAL(20,4)) AS rafval
, CAST(COALESCE(ed3.DClose,0) AS DECIMAL(20,4)) AS ralval
, CAST(COALESCE(ed4.DClose,0) AS DECIMAL(20,4)) AS rbfval
, CAST(COALESCE(ed5.DClose,0) AS DECIMAL(20,4)) AS rblval
, CAST(COALESCE(ed6.DClose,0) AS DECIMAL(20,4)) AS rcfval
, CAST(COALESCE(ed7.DClose,0) AS DECIMAL(20,4)) AS rclval
, COALESCE(ed.vstd,0) AS vstd
FROM (
SELECT
ed.Isin
, MIN(IF( DDate >= now()-INTERVAL 12 MONTH, EodDataId, NULL)) AS id_rafval
, MAX(IF( DDate >= now()-INTERVAL 12 MONTH, EodDataId, NULL)) AS id_ralval
, MIN(IF( DDate >= now()-INTERVAL 3 MONTH, EodDataId, NULL)) AS id_rbfval
, MAX(IF( DDate >= now()-INTERVAL 3 MONTH, EodDataId, NULL)) AS id_rblval
, MIN(IF( DDate >= now()-INTERVAL 40 DAY , EodDataId, NULL)) AS id_rcfval
, MAX(IF( DDate >= now()-INTERVAL 40 DAY , EodDataId, NULL)) AS id_rclval
, std(IF( DDate >= now()-INTERVAL 40 DAY , NULL, DClose )) AS vstd
FROM eod_data ed
WHERE ed.DDate >= now()-INTERVAL 12 MONTH
GROUP BY ed.Isin
ORDER BY ed.EodDataId ASC
) ed
LEFT JOIN eod_data ed2 ON ed2.Isin = ed.Isin AND ed2.EodDataId = ed.id_rafval
LEFT JOIN eod_data ed3 ON ed3.Isin = ed.Isin AND ed3.EodDataId = ed.id_ralval
LEFT JOIN eod_data ed4 ON ed4.Isin = ed.Isin AND ed4.EodDataId = ed.id_rbfval
LEFT JOIN eod_data ed5 ON ed5.Isin = ed.Isin AND ed5.EodDataId = ed.id_rblval
LEFT JOIN eod_data ed6 ON ed6.Isin = ed.Isin AND ed6.EodDataId = ed.id_rcfval
LEFT JOIN eod_data ed7 ON ed7.Isin = ed.Isin AND ed7.EodDataId = ed.id_rclval
INNER JOIN assets a ON a.Isin = ed.Isin
INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
WHERE asg.AssetGroupId=1
AND a.IsActive=1
ORDER BY a.AssetId;
SELECT
a.AssetId
, a.AssetName
, a.Isin
, CAST(COALESCE(ed2.DClose,0) AS DECIMAL(20,4)) AS rafval
, CAST(COALESCE(ed3.DClose,0) AS DECIMAL(20,4)) AS ralval
, CAST(COALESCE(ed4.DClose,0) AS DECIMAL(20,4)) AS rbfval
, CAST(COALESCE(ed5.DClose,0) AS DECIMAL(20,4)) AS rblval
, CAST(COALESCE(ed6.DClose,0) AS DECIMAL(20,4)) AS rcfval
, CAST(COALESCE(ed7.DClose,0) AS DECIMAL(20,4)) AS rclval
FROM (
SELECT
ed.Isin
, MIN(IF( DDate >= now()-INTERVAL 12 MONTH, EodDataId, NULL)) AS id_rafval
, MAX(IF( DDate >= now()-INTERVAL 12 MONTH, EodDataId, NULL)) AS id_ralval
, MIN(IF( DDate >= now()-INTERVAL 3 MONTH, EodDataId, NULL)) AS id_rbfval
, MAX(IF( DDate >= now()-INTERVAL 3 MONTH, EodDataId, NULL)) AS id_rblval
, MIN(IF( DDate >= now()-INTERVAL 20 DAY , EodDataId, NULL)) AS id_rcfval
, MAX(IF( DDate >= now()-INTERVAL 20 DAY , EodDataId, NULL)) AS id_rclval
FROM eod_data ed
WHERE ed.DDate >= now()-INTERVAL 12 MONTH
GROUP BY ed.Isin
ORDER BY ed.DDate ASC
) ed
LEFT JOIN eod_data ed2 ON ed2.Isin = ed.Isin AND ed2.EodDataId = ed.id_rafval
LEFT JOIN eod_data ed3 ON ed3.Isin = ed.Isin AND ed3.EodDataId = ed.id_ralval
LEFT JOIN eod_data ed4 ON ed4.Isin = ed.Isin AND ed4.EodDataId = ed.id_rbfval
LEFT JOIN eod_data ed5 ON ed5.Isin = ed.Isin AND ed5.EodDataId = ed.id_rblval
LEFT JOIN eod_data ed6 ON ed6.Isin = ed.Isin AND ed6.EodDataId = ed.id_rcfval
LEFT JOIN eod_data ed7 ON ed7.Isin = ed.Isin AND ed7.EodDataId = ed.id_rclval
INNER JOIN assets a ON a.Isin = ed.Isin
INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
WHERE asg.AssetGroupId=1
AND a.IsActive=1
ORDER BY a.AssetId;
你可以再试一次吗?