3

我在一个名为的表中有以下数据:dbo.DecodedCSVMessages_Staging

以下是数据示例:

MMSI     Message_ID    Time     Ship_Type  Vessel_Name   Latitude   Longitude

2102930      3       2012-06-01     NULL      NULL       56.528003  85.233443

2102930      5       2012-07-01      70     RIO_CUBAL      NULL      NULL

2109300      1       2012-08-01     NULL      NULL       57.43234   131.123343

2109300      1       2012-09-01     NULL      NULL       62.432345  121.123343

2109300      1       2012-09-02     NULL      NULL       65.432345  140.123343

2109300      5       2012-08-01      70     RIO_CUBAL      NULL       NULL

2225555      1       2012-08-01     NULL      NULL       66.432345  143.123343

2225555      1       2012-09-01     NULL      NULL       25.432345  145.123343

2225555      5       2012-08-01      70      RIO_II        NULL       NULL

我需要的是如下:

  • MMSI 编号是代表船舶的唯一编号。一艘船以独特的消息类型发送不同的信息。我只对 Message_ID 1 和 3 感兴趣,因为它们具有纬度和纵向信息。MMSI 将在此数据库中重新出现(如上数据所示)
  • 问题是,我需要有关这艘船的信息,不幸的是,该信息仅在 Message_ID 5 中可用。例如 Vessel_name 和 Ship_type。
  • 我只需要在以下经纬度范围内的船舶

  • Ship_Type 可能会改变!在这种情况下,它必须反映较晚的日期

    其中纬度 > 55 和纬度 <85 和经度 > 50 和经度 < 141;

查询数据的结果将产生以下结果(其中我将保存为 CSV 格式,因为我正在使用此信息在 ArcGIS 中构建点要素)

MMSI     Message_ID    Time    Ship_Type  Vessel_Name   Latitude   Longitude

2102930      3       2012-06-01     70     RIO_CUBAL    56.528003  85.233443

2109300      1       2012-08-01     70     RIO_CUBAL    57.43234   131.123343

2109300      1       2012-09-01     70     RIO_CUBAL    62.432345  121.123343

2109300      1       2012-09-02     70     RIO_CUBAL    65.432345  140.123343

2225555      1       2012-08-01     70      RIO_II      66.432345  143.123343
  • 所以所有 Message_ID 5 都消失了

  • 倒数第二行消失了(因为纬度只有 25.432345)

  • 信息 Ship_Type 和 Vessel_Name 已通过使用 MMSI 链接的方式添加到 Message_ID 1 和 3。

约束:

  1. 无法创建新表(无权访问)
  2. 该数据库中有超过 10 亿行数据(尽管只有大约 430 万行符合经纬度限制)

查询可能是什么???谢谢!

4

6 回答 6

5

这样的事情应该这样做:

; WITH positions AS (
  SELECT MMSI
       , Message_ID
       , "Time"
       , Latitude
       , Longitude
  FROM   dbo.DecodedCSVMessages_Staging
  WHERE  Message_ID IN (1, 3)
  AND    Latitude  > 55
  AND    Latitude  < 85
  AND    Longitude > 50
  AND    Longitude < 141
)
, details AS (
  SELECT MMSI
       , Ship_Type
       , Vessel_Name
       , Row_Number() OVER (PARTITION BY MMSI ORDER BY "Time" DESC) As row_num
  FROM   dbo.DecodedCSVMessages_Staging
  WHERE  Message_ID = 5
)
SELECT positions.MMSI
     , positions.Message_ID
     , positions."Time"
     , details.Ship_Type
     , details.Vessel_Name
     , positions.Latitude
     , positions.Longitude
FROM   positions
 INNER
  JOIN details
    ON details.MMSI    = positions.MMSI
   AND details.row_num = 1 -- Limit to "latest" ship details per MMSI
于 2013-09-17T13:23:57.757 回答
1

我认为它相对简单......就像......

select
      MS.MMSI,
      MS.Message_ID,
      MS.Time,
      Ship.Ship_Type,
      Ship.Vessel_Name,
      MS.Latitude,
      MS.Longitude
   from
      dbo.DecodedCSVMessages_Staging MS
         JOIN dbo.DecodedCSVMessages_Staging Ship
            on MS.MMSI = Ship.MMSI
           AND Ship.Message_ID = 5
   where
          MS.Message_ID in ( 1, 3 )
      AND MS.Latitude > 55
      AND MS.Latitude < 85
      AND MS.Longitude > 50
      AND MS.Longitude < 141

我还建议对

(MMSI、Message_ID、纬度、经度)

所以它涵盖了您正在寻找的尽可能多的标准和加入条件

于 2013-09-17T13:27:48.147 回答
0
WITH SHIP_CTE (Vessel_name,Ship_type,MMSI)
(SELECT Vessel_name, Ship_type,MMSI FROM DecodedCSVMessages_Staging WHERE Message_Id=5)
SELECT A.MMSI,Message_ID, Time,B.Ship_Type,B.Vessel_Name, Latitude,
Longitude FROM DecodedCSVMessages_Staging  A JOIN SHIP_CTE B ON A.MMSI=B.MMSI
where Latitude > 55 and Latitude <85 and Longitude > 50 and Longitude < 141
于 2013-09-17T13:27:09.990 回答
0

我记得,有一种方法可以在暂存表之前进行过滤。业务流程外包,我认为。这是将 CSV 读入临时表的命令行实用程序。如果可能的话,将行数减少到 4% 可能是一个好策略。

我记得您甚至可以将 CSV 拆分为相关表。不久前,我将 200 万行的数据导入到 8-10 个表中,这些表在不到 30 秒的时间内完成。

于 2013-09-17T13:33:22.737 回答
0

看到原始选择的帖子,用“最近的 ID = 5 条目”制定了我的解决方案,然后看到了更新的获奖帖子。无论如何都要扔掉我的,以展示如何在没有 CTE 的情况下完成它。(我知道人们喜欢 CTE,但我发现它们比简单的子查询更难阅读和理解。)

SELECT
   M13.MMSI
  ,M13.Message_ID
  ,M13.Time
  ,RecentM5.Ship_Type
  ,RecentM5.Vessel_Name
  ,M13.Latitude
  ,M13.Longitude
 from dbo.DecodedCSVMessages_Staging M13
  inner join (--  Most recent "Message_ID = 5" entry for each MMSI (i.e. most recent name)
              select MMSI, Ship_Type, Vessel_Name
               from (--  All MMSI, set "Ranking" = 1 for the most recent entry
                     select MMSI, Ship_Type, Vessel_Name, row_number() over (partition by MMSI order by Time desc) Ranking
                      from dbo.DecodedCSVMessages_Staging
                      where Message_ID = 5) AllM5
               where Ranking = 1) RecentM5
   on RecentM5.MMSI = M13.MMSI
 where M13.Message_ID <> 5  --  Assumes Message_ID can only be 1,3,5, ortherwise use (slower) IN clause
  and M13.Latitude between 55 and 85
  and M13.Longitude between 50 and 141

至于“超过十亿行”,解决这个问题的最佳方法是使用索引......但您似乎可能必须至少读取表中的每一行一次。虽然 Latitude、Longitude 和 Message_ID 上的索引都显示了它们自己,但数据的性质意味着低基数 - 即,您的数据的大部分将属于您的过滤条件,使表扫描成为读取数据的最有效方式. 您是否需要担心锁定或阻塞问题?

于 2013-09-17T13:52:35.377 回答
-1

我认为这个查询会做。

SELECT MMSI, MESSAGE_ID, TIME, SHIP_TYPE, VESSEL_NAME, LATITUDE, LONGITUDE FROM
(
SELECT MMSI, MESSAGE_ID, TIME, SHIP_TYPE, VESSEL_NAME, LATITUDE, LONGITUDE FROM TABLE where Latitude > 55 and Latitude <85 and Longitude > 50 and Longitude < 141  AND MESSAGE_ID IN (3,1) ) A
(
SELECT MMSI, MESSAGE_ID, TIME, SHIP_TYPE, VESSEL_NAME, LATITUDE, LONGITUDE FROM TABLE WHERE
MESSAGE_ID= 5) B WHERE A.MMSI=B.MMSI AND A.MESSAGE_ID IN (3,1)

谢谢尼拉吉·拉蒂

于 2013-09-17T13:25:38.143 回答