删除分钟。在比较sql中的表中的两个值之后来自记录的值

时间:2017-08-07 11:56:39

标签: mysql sql

我需要帮助来过滤表格中的数据:tbl_entso_cdbf。 该表包含从一个地区到其他地区的贸易信息:

  Utc             |      date         |area_in|area_out|  value  | 
------------------------------------------------------------------
2015-12-05T03:00Z |2015-12-05 03:00:00| 275   |  40    |   320   |
2015-12-05T03:00Z |2015-12-05 03:00:00| 40    |  275   |   0     |
2015-12-06T03:00Z |2015-12-06 03:00:00| 100   |  175   |   550   |
2015-12-06T03:00Z |2015-12-06 03:00:00| 175   |  100   |   0     |
2015-11-04T03:00Z |2015-11-04 03:00:00| 280   |  310   |   0     |
2015-11-04T03:00Z |2015-11-04 03:00:00| 310   |  280   |   0     |
2016-09-19T00:00Z |2016-09-19 00:00:00| 187   |  292   |   45    |
2016-09-19T00:00Z |2016-09-19 00:00:00| 292   |  187   |   0     |

表格包含area_inarea_out之间的导出和导入值。 此表包含值列中的双重条目,引用date列。例如,前两行具有相同的日期和时间2015-12-05 03:00:00,但有两个不同的值3200。我希望只有一个值320并删除具有0值的第二行。这意味着在同一日期和时间275下,area_in 40和area_out 2015-12-05 03:00:00之间的交易应具有唯一的正值。同样意味着行号。 3,4,7和8。 但是在第5行和第6行中都有0个值,所以我想只有一个记录(其中任何一个)。

所以,最后我希望我的表看起来像:

Utc               |      date         |area_in|area_out|  value  | 
------------------------------------------------------------------
2015-12-05T03:00Z |2015-12-05 03:00:00| 275   |  40    |   320   |
2015-12-06T03:00Z |2015-12-06 03:00:00| 100   |  175   |   550   |
2015-11-04T03:00Z |2015-11-04 03:00:00| 310   |  280   |   0     |
2016-09-19T00:00Z |2016-09-19 00:00:00| 187   |  292   |   45    |

此表有数百万种此类行要过滤。任何人都可以帮我写一个SQL查询吗?

2 个答案:

答案 0 :(得分:0)

我假设你的主键表看起来像这样:

      pk |   Utc             |      date         |area_in|area_out|  value  | 
      -----------------------------------------------------------------------
       1 | 2015-12-05T03:00Z |2015-12-05 03:00:00| 275   |  40    |   320   |
       2 | 2015-12-05T03:00Z |2015-12-05 03:00:00| 40    |  275   |   0     |
       3 | 2015-12-06T03:00Z |2015-12-06 03:00:00| 100   |  175   |   550   |
       4 | 2015-12-06T03:00Z |2015-12-06 03:00:00| 175   |  100   |   0     |
       5 | 2015-11-04T03:00Z |2015-11-04 03:00:00| 280   |  310   |   0     |
       6 | 2015-11-04T03:00Z |2015-11-04 03:00:00| 310   |  280   |   0     |
       7 | 2016-09-19T00:00Z |2016-09-19 00:00:00| 187   |  292   |   45    |
       8 | 2016-09-19T00:00Z |2016-09-19 00:00:00| 292   |  187   |   0     |

执行此查询后,您应该能够删除要删除的行:

 DELETE FROM  tbl_entso_cdbf
 WHERE pk IN (SELECT PK_DEL
             FROM (Select   pk AS PK_DEL
                          , utc
                          , value
                          , ROW_NUMBER() OVER(PARTITION BY utc ORDER BY value desc) AS DUB_IND
                   FROM tbl_entso_cdbf 
                   WHERE DUB_IND <> 1
                   )
             ); 

该查询用于删除子查询返回中pk in的所有行。子查询应返回记录的所有主键,其中值为次要值作为重复项。但是,在尝试使用shure之前,请查询此查询返回应删除的记录的所需结果:

Select   pk AS PK_DEL
       , utc
       , value
       , ROW_NUMBER() OVER(PARTITION BY utc ORDER BY value desc) AS DUB_IND
FROM tbl_entso_cdbf 
WHERE DUB_IND <> 1

如果是这样,您应该能够删除重复项!

答案 1 :(得分:0)

使用此查询查找要删除的行:

select t0.* 
from tbl_entso_cdbf t0
join tbl_entso_cdbf t1
  on  t1.Utc  = t0.Utc
  and t1.date = t0.date
  and t1.area_in  = t0.area_out
  and t1.area_out = t0.area_in
where t0.value = 0
  and (t1.value <> 0 or t1.area_in < t0.area_in);

条件是:

  • value = 0
  • 还有另一行具有相同的Utc和相同的date,但area_inarea_out已切换。
  • 另一行的value不是0 area_in更小。

查询将返回以下行:

|               Utc |                date | area_in | area_out | value |
|-------------------|---------------------|---------|----------|-------|
| 2015-12-05T03:00Z | 2015-12-05 03:00:00 |      40 |      275 |     0 |
| 2015-12-06T03:00Z | 2015-12-06 03:00:00 |     175 |      100 |     0 |
| 2015-11-04T03:00Z | 2015-11-04 03:00:00 |     310 |      280 |     0 |
| 2016-09-19T00:00Z | 2016-09-19 00:00:00 |     292 |      187 |     0 |

现在在delete语句的子查询中使用它:

delete t1
from tbl_entso_cdbf t1
natural join (
    select t0.*
    from tbl_entso_cdbf t0
    join tbl_entso_cdbf t1
      on  t1.Utc  = t0.Utc
      and t1.date = t0.date
      and t1.area_in  = t0.area_out
      and t1.area_out = t0.area_in
    where t0.value = 0
      and (t1.value <> 0 or t1.area_in < t0.area_in)    
) t0;

NATURAL JOIN表示所有列值必须相等。如果您有主键(或任何唯一键),则只需选择子查询中的主(唯一)键列而不是*

现在表中只剩下以下行:

|               Utc |                date | area_in | area_out | value |
|-------------------|---------------------|---------|----------|-------|
| 2015-12-05T03:00Z | 2015-12-05 03:00:00 |     275 |       40 |   320 |
| 2015-12-06T03:00Z | 2015-12-06 03:00:00 |     100 |      175 |   550 |
| 2015-11-04T03:00Z | 2015-11-04 03:00:00 |     280 |      310 |     0 |
| 2016-09-19T00:00Z | 2016-09-19 00:00:00 |     187 |      292 |    45 |