如何在电力设备数据表连接中避免笛卡尔积?
解决两张表连接产生笛卡尔积的问题
需要连接两张表:
MDO_PROGDIA_POTDISPONIBLE:存储各发电设备每日每小时的可用功率(AV_POWER)MDO_PROGDIA_COSTOSVARIABLES:存储各发电设备每日每小时的可变成本(VAR_COST)
两张表均包含PROG_NUM(预测编号)字段,本次仅需处理编号为-1的预测数据。当前SQL执行后出现笛卡尔积,需获取DATE、HOUR、EQUIP唯一组合对应的单行数据。
表数据示例
MDO_PROGDIA_POTDISPONIBLE表数据
| DATE | HOUR | EQUIP | PROG_NUM | AV_POWER |
|---|---|---|---|---|
| 07/18/23 | 0 | 15se-g1 | -1 | 185.52 |
| 07/18/23 | 0 | 5nov-u1 | -1 | 19.5 |
| 07/18/23 | 0 | 5nov-u2 | -1 | 19.5 |
| 07/18/23 | 0 | 5nov-u3 | -1 | 19.5 |
| 07/18/23 | 0 | 5nov-u4 | -1 | 2.08696 |
| 07/18/23 | 0 | 5nov-u5 | -1 | 0 |
| 07/18/23 | 0 | 5nov-u6 | -1 | 40.07 |
| 07/18/23 | 0 | 5nov-u7 | -1 | 40.07 |
| 07/18/23 | 0 | acaj-g2 | -1 | 3.31683 |
| 07/18/23 | 0 | acaj-m1 | -1 | 2.72333 |
| 07/18/23 | 0 | acaj-m2 | -1 | 2.72333 |
| 07/18/23 | 0 | acaj-m3 | -1 | 0 |
| 07/18/23 | 0 | acaj-m4 | -1 | 2.72333 |
| 07/18/23 | 0 | acaj-m5 | -1 | 2.72333 |
| 07/18/23 | 0 | acaj-m6 | -1 | 2.72333 |
| 07/18/23 | 0 | acaj-u1 | -1 | 24.71 |
| 07/18/23 | 0 | acaj-u2 | -1 | 24.85 |
| 07/18/23 | 0 | acaj-u4 | -1 | 27.94 |
| 07/18/23 | 0 | acaj-u5 | -1 | 64.32 |
MDO_PROGDIA_COSTOSVARIABLES表数据
| DATE | HOUR | EQUIP | VAR_COST | PROG_NUM |
|---|---|---|---|---|
| 07/18/23 | 0 | 15se-g1 | 92.270483 | -1 |
| 07/18/23 | 0 | 5nov-u1 | 72.82923895 | -1 |
| 07/18/23 | 0 | 5nov-u2 | 72.82923895 | -1 |
| 07/18/23 | 0 | 5nov-u3 | 72.82923895 | -1 |
| 07/18/23 | 0 | 5nov-u4 | 72.82923895 | -1 |
| 07/18/23 | 0 | 5nov-u5 | 72.82923895 | -1 |
| 07/18/23 | 0 | 5nov-u6 | 72.82923895 | -1 |
| 07/18/23 | 0 | 5nov-u7 | 72.82923895 | -1 |
| 07/18/23 | 0 | acaj-g2 | 125.85 | -1 |
| 07/18/23 | 0 | acaj-m1 | 132.88 | -1 |
| 07/18/23 | 0 | acaj-m2 | 132.88 | -1 |
| 07/18/23 | 0 | acaj-m3 | 132.88 | -1 |
| 07/18/23 | 0 | acaj-m4 | 132.88 | -1 |
| 07/18/23 | 0 | acaj-m5 | 132.88 | -1 |
| 07/18/23 | 0 | acaj-m6 | 132.88 | -1 |
| 07/18/23 | 0 | acaj-u1 | 214.17 | -1 |
| 07/18/23 | 0 | acaj-u2 | 215.18 | -1 |
| 07/18/23 | 0 | acaj-u4 | 364.33 | -1 |
| 07/18/23 | 0 | acaj-u5 | 302.96 | -1 |
| 07/18/23 | 0 | ahua-u1 | 4.819 | -1 |
| 07/18/23 | 0 | ahua-u2 | 4.819 | -1 |
| 07/18/23 | 0 | ahua-u3 | 4.15 | -1 |
当前使用的SQL代码
select p.DATE, p.HOUR, p.EQUIP, p.AV_POWER, c.VAR_COST FROM MDO_PROGDIA_POTDISPONIBLE p JOIN MDO_PROGDIA_COSTOSVARIABLES c ON p.DATE = c.DATE AND p.HOUR = c.HOUR AND p.EQUIP = c.EQUIP WHERE p.DATE = to_date(:ddmmaa,'DDMMYY') ORDER BY p.DATE, p.HOUR, c.VAR_COST, p.EQUIP
问题原因与解决方案
问题原因
当前SQL未将PROG_NUM纳入连接条件,若同一设备在同一时间存在多个PROG_NUM的记录,会跨预测编号匹配,导致产生笛卡尔积;此外,如果某张表内存在DATE+HOUR+EQUIP+PROG_NUM的重复行,也会导致连接后行数翻倍。
解决方案
方案1:添加PROG_NUM连接与过滤条件(适用于表中无重复主键组合的情况)
在JOIN条件中匹配PROG_NUM,并在WHERE子句中过滤目标预测编号,确保仅匹配同一预测的记录:
SELECT p.DATE, p.HOUR, p.EQUIP, p.AV_POWER, c.VAR_COST FROM MDO_PROGDIA_POTDISPONIBLE p JOIN MDO_PROGDIA_COSTOSVARIABLES c ON p.DATE = c.DATE AND p.HOUR = c.HOUR AND p.EQUIP = c.EQUIP AND p.PROG_NUM = c.PROG_NUM -- 新增:匹配同一预测编号 WHERE p.DATE = TO_DATE(:ddmmaa, 'DDMMYY') AND p.PROG_NUM = -1 -- 过滤目标预测编号 AND c.PROG_NUM = -1 ORDER BY p.DATE, p.HOUR, c.VAR_COST, p.EQUIP
方案2:先去重再连接(适用于表中存在重复记录的情况)
若某张表内存在DATE+HOUR+EQUIP+PROG_NUM的重复行,先通过DISTINCT去重,再进行连接:
SELECT p.DATE, p.HOUR, p.EQUIP, p.AV_POWER, c.VAR_COST FROM -- 对可用功率表去重 (SELECT DISTINCT DATE, HOUR, EQUIP, PROG_NUM, AV_POWER FROM MDO_PROGDIA_POTDISPONIBLE WHERE PROG_NUM = -1) p JOIN -- 对可变成本表去重 (SELECT DISTINCT DATE, HOUR, EQUIP, PROG_NUM, VAR_COST FROM MDO_PROGDIA_COSTOSVARIABLES WHERE PROG_NUM = -1) c ON p.DATE = c.DATE AND p.HOUR = c.HOUR AND p.EQUIP = c.EQUIP AND p.PROG_NUM = c.PROG_NUM WHERE p.DATE = TO_DATE(:ddmmaa, 'DDMMYY') ORDER BY p.DATE, p.HOUR, c.VAR_COST, p.EQUIP
效果说明
通过上述调整,可确保每个DATE+HOUR+EQUIP组合仅返回一行对应的数据,避免笛卡尔积问题。
内容的提问来源于stack exchange,提问作者oavaldezi
相关产品推荐
相关产品推荐

