SQL:如果该值在同一列中的任何位置可用,则将一个值与整列进行比较。为这两个值之间的每个值命名

问题描述 投票:0回答:1
创建日期 rake_device rounded_geo_lat rounded_geo_lng 闲置或移动 新空闲移动
2024年8月1日11:27 a-b 28.29 76.39 空闲 空闲
2024年8月1日10:27 a-b 28.29 76.39 空闲 空闲
2024年8月1日09:27 a-b 28.29 76.39 空闲 空闲
2024年8月1日08:27 a-b 28.29 76.39 空闲 空闲
2024年8月1日07:27 a-b 28.29 76.39 空闲 空闲
2024年8月1日06:27 a-b 28.29 76.39 移动 空闲
2024年8月1日05:27 a-b 28.28 76.39 移动 空闲
2024年8月1日05:21 a-b 28.29 76.39 空闲 空闲
2024年8月1日05:12 a-b 28.29 76.39 空闲 空闲
2024年8月1日04:12 a-b 28.29 76.39 空闲 空闲
2024年8月1日03:12 a-b 28.29 76.39 空闲 空闲
2024年8月1日02:12 a-b 28.24 76.39 移动 移动
2024年8月1日03:13 a-b 28.24 76.39 移动 移动
2024年8月1日03:09 a-b 28.245 76.33129 移动 移动
2024年8月1日05:12 a-b 28.324 76.3921 空闲 空闲
2024年8月1日05:12 a-b 28.324 76.3921 空闲 空闲

根据以上数据,我想导出新的列

new_idle_moving
。本专栏的逻辑是:I

我必须评估

rounded_geo_lat,rounded_geo_lng
的每一对值。如果在该分区之间的任何位置找到相同的对(rake_device、created_date desc),那么它们之间的所有值都应标记为
idle
并按原样移动。

注意:如果该移动标签的前后 lat、lng 相同,我们只需将这些移动标签替换为空闲标签即可。并且数据采用增量格式,因此每个新小时都会生成新条目,因此我们必须将其与 LAT LNG 的整个列进行比较。

我尝试了以下查询,但它将所有值转换为空闲,这是错误的输出。

  WITH GroupedData AS (
  SELECT
    created_date,
    rake_device,
    rounded_geo_lat,
    rounded_geo_lng,
    idle_or_moving,
    MAX(idle_or_moving) OVER (PARTITION BY rake_device, grp ORDER BY created_date DESC) AS max_idle_or_moving
  FROM (
    SELECT
      created_date,
      rake_device,
      rounded_geo_lat,
      rounded_geo_lng,
      idle_or_moving,
      SUM(change_flag) OVER (PARTITION BY rake_device ORDER BY created_date DESC) AS grp
    FROM (
      SELECT
        created_date,
        rake_device,
        rounded_geo_lat,
        rounded_geo_lng,
        idle_or_moving,
        CASE WHEN LAG(rounded_geo_lat) OVER (PARTITION BY rake_device ORDER BY created_date DESC) = rounded_geo_lat
               AND LAG(rounded_geo_lng) OVER (PARTITION BY rake_device ORDER BY created_date DESC) = rounded_geo_lng
             THEN 0 ELSE 1 END AS change_flag
      FROM YourTable
    ) AS ChangeFlag
  ) AS GrpAssign
)
SELECT
  gd.created_date,
  gd.rake_device,
  gd.rounded_geo_lat,
  gd.rounded_geo_lng,
  gd.idle_or_moving,
  CASE WHEN gd.max_idle_or_moving = 'idle' THEN 'idle' ELSE gd.idle_or_moving END AS new_idle_moving
FROM GroupedData gd
ORDER BY gd.created_date DESC;

这里是数据库小提琴链接:https://dbfiddle.uk/w5pNGy5B

sql mysql
1个回答
0
投票

尚不清楚您希望如何调节 NEW_IDLE_MOVING 列,但您可以使用 LAG() 和 LEAD() 分析函数从上一行/下一行获取数据。答案中添加了一些其他列,可以帮助您创建将“移动”更改为“空闲”的正确条件。我的最终结果有两个新列,一列具有相同的上一个和下一个值 (_AND),另一列具有上一个或下一个相同的值 (_OR)。目前尚不清楚您需要什么,因为您提到了与上一行/下一行相同的值,并且后来影响了具有相同值的所有值。不管怎样,如果你尝试实现下面的示例,你就会明白:

WITH    --  S a m p l e    D a t a :
    data_new (CREATED_DATE, RAKE_DEVICE, ROUNDED_GEO_LAT, ROUNDED_GEO_LNG, IDLE_OR_MOVING) AS
        ( Select STR_TO_DATE('2024-08-01 11:27:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 10:27:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 09:27:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 08:27:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 07:27:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 06:27:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'moving' From Dual Union All
          Select STR_TO_DATE('2024-08-01 05:27:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.28, 76.39, 'moving' From Dual Union All
          Select STR_TO_DATE('2024-08-01 05:21:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 05:12:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 04:12:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 03:12:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.29, 76.39, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 02:12:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.24, 76.39, 'moving' From Dual Union All
          Select STR_TO_DATE('2024-08-01 03:13:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.24, 76.39, 'moving' From Dual Union All
          Select STR_TO_DATE('2024-08-01 03:09:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.245, 76.33129, 'moving' From Dual Union All
          Select STR_TO_DATE('2024-08-01 05:12:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.324, 76.3921, 'idle' From Dual Union All
          Select STR_TO_DATE('2024-08-01 05:12:00', '%Y-%m-%d %H:%i:%s'), 'a-b', 28.324, 76.3921, 'idle' From Dual 
        )
--  M a i n    S Q L :
SELECT    a.CREATED_DATE, a.RAKE_DEVICE, a.ROUNDED_GEO_LAT, a.ROUNDED_GEO_LNG,
          a.IDLE_OR_MOVING,
          Case When a.LAT_LNG = a.PREV_LAT_LNG And a.LAT_LNG = a.NEXT_LAT_LNG
               Then 'idle'
          Else a.IDLE_OR_MOVING
          End "NEW_IDLE_MOVING_WITH_AND",
          Case When a.LAT_LNG = a.PREV_LAT_LNG Or a.LAT_LNG = a.NEXT_LAT_LNG
               Then 'idle'
          Else a.IDLE_OR_MOVING
          End "NEW_IDLE_MOVING_WITH_OR",
          a.DATE_START, a.DATE_END
FROM
  ( Select CREATED_DATE, RAKE_DEVICE, ROUNDED_GEO_LAT, ROUNDED_GEO_LNG, 
           IDLE_OR_MOVING,
           Concat(ROUNDED_GEO_LAT, ' - ', ROUNDED_GEO_LNG) "LAT_LNG",
           Concat(Coalesce(Lag(ROUNDED_GEO_LAT) Over(Order By CREATED_DATE Desc), ROUNDED_GEO_LAT), 
                  ' - ',
                  Coalesce(Lag(ROUNDED_GEO_LNG) Over(Order By CREATED_DATE Desc), ROUNDED_GEO_LNG)
           ) "PREV_LAT_LNG", 
           Concat(Coalesce(Lead(ROUNDED_GEO_LAT) Over(Order By CREATED_DATE Desc), ROUNDED_GEO_LAT), 
                  ' - ',
                  Coalesce(Lead(ROUNDED_GEO_LNG) Over(Order By CREATED_DATE Desc), ROUNDED_GEO_LNG)
           ) "NEXT_LAT_LNG",
           Coalesce(Lag(ROUNDED_GEO_LAT) Over(Order By CREATED_DATE Desc), ROUNDED_GEO_LAT) "LAT_PREV",
           Coalesce(Lead(ROUNDED_GEO_LAT) Over(Order By CREATED_DATE Desc), ROUNDED_GEO_LAT) "LAT_NEXT",
           Coalesce(Lag(ROUNDED_GEO_LNG) Over(Order By CREATED_DATE Desc), ROUNDED_GEO_LNG) "LNG_PREV",
           Coalesce(Lead(ROUNDED_GEO_LNG) Over(Order By CREATED_DATE Desc), ROUNDED_GEO_LNG) "LNG_NEXT",
           Min(CREATED_DATE) Over(Partition By Concat(ROUNDED_GEO_LAT, ' - ', ROUNDED_GEO_LNG)) "DATE_START", 
           Max(CREATED_DATE) Over(Partition By Concat(ROUNDED_GEO_LAT, ' - ', ROUNDED_GEO_LNG)) "DATE_END"
    From      data_new
    Order By  CREATED_DATE Desc, ROUNDED_GEO_LAT, ROUNDED_GEO_LNG
  ) a
/*          R e s u l t :
CREATED_DATE        RAKE_DEVICE ROUNDED_GEO_LAT ROUNDED_GEO_LNG IDLE_OR_MOVING  NEW_IDLE_MOVING_WITH_AND    NEW_IDLE_MOVING_WITH_OR DATE_START          DATE_END
------------------- ----------- --------------- --------------- --------------- --------------------------- ----------------------- ------------------- --------------------  
2024-08-01 11:27:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 10:27:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 09:27:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 08:27:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 07:27:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 06:27:00 a-b                 28.290      76.39000    moving          moving                      idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 05:27:00 a-b                 28.280      76.39000    moving          moving                      moving                  2024-08-01 05:27:00 2024-08-01 05:27:00
2024-08-01 05:21:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 05:12:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 05:12:00 a-b                 28.324      76.39210    idle            idle                        idle                    2024-08-01 05:12:00 2024-08-01 05:12:00
2024-08-01 05:12:00 a-b                 28.324      76.39210    idle            idle                        idle                    2024-08-01 05:12:00 2024-08-01 05:12:00
2024-08-01 04:12:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 03:13:00 a-b                 28.240      76.39000    moving          moving                      moving                  2024-08-01 02:12:00 2024-08-01 03:13:00
2024-08-01 03:12:00 a-b                 28.290      76.39000    idle            idle                        idle                    2024-08-01 03:12:00 2024-08-01 11:27:00
2024-08-01 03:09:00 a-b                 28.245      76.33129    moving          moving                      moving                  2024-08-01 03:09:00 2024-08-01 03:09:00
2024-08-01 02:12:00 a-b                 28.240      76.39000    moving          moving                      idle                    2024-08-01 02:12:00 2024-08-01 03:13:00                                     */

...您可以在 https://dbfiddle.uk/NsFrZsln

进行测试
© www.soinside.com 2019 - 2024. All rights reserved.