【问题标题】:SQL Server 2008 Complex Query & Table JoinSQL Server 2008 复杂查询和表连接
【发布时间】:2013-09-13 16:26:58
【问题描述】:

这有点难以解释,但我会尽力而为。我有一个数据库,用于维护有关海运等的信息。我有以下几列可供使用。 (还有其他的,但它们对我的研究没有任何目的)我有 Message_ID、纬度、经度、MMSI(这代表个别船舶信号,因此它们是船舶独有的)Ship_type、Vessel_name。

问题来了

  • 我只需要 Message_ID 的 1 和 3。
  • 不幸的是,Message_ID 的 1 和 3 在它们各自的位置中将 Ship_type 和 Vessel_name 设为 Null。
  • Message_ID 5 标记了 Ship_type 和 Vessel_name。
  • 我的研究区域在给定的经纬度范围内

基本上我需要做的是将 Ship_type 和 Vessel_name 附加到 Message_ID 为 1 和 3 的行,方法是通过 Message_ID 5 共享的 MMSI 号加入。

到目前为止我的查询..

WHERE (latitude > 55 and latitude < 85 and longitude > 50 and longitude < 141) And (Message_ID = 1 or Message_ID = 3);

其他查询

WHERE Message_ID = 5;

如何将导致第二个查询的所有 Ship_type 和 Vessel_name 连接到第一个查询?

我觉得应该提到所有内容都在一个名为 dbo.DecodedCSVMEssages_Staging 的表中,该表有大约 1 亿个条目..:S

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    我可能会这样做:

    SELECT
         t13.Message_ID, 
         t13.Latitude, 
         t13.Longitude, 
         t13.MMSI,
         t5.Ship_type, 
         t5.Vessel_name
    FROM yourTable As t13
    OUTER APPLY (   SELECT TOP 1 * 
                    FROM  yourTable As t5
                    WHERE t5.Message_ID = 5
                      AND t5.MMSI = t13.MMSI
                 ) As t5
    WHERE t13.Message_ID IN(1,3)
      AND t13.latitude > 55 
      and t13.latitude < 85 
      and t13.longitude > 50 
      and t13.longitude < 141
    

    【讨论】:

    • t13.和 t5。代表什么?
    • @dpalm 这是一种方便的语法,称为table alias
    • 所以基本上你给表名起了别名?
    • 是的,它与SELECT yourTable.Message_ID, [...] 相同,但可以减少输入,更重要的是允许子查询明确引用外部查询中的表(在本例中为OUTER APPLY 部分)。
    • @dpalm 是的。当您不想弄乱列名的长表名时,它们很方便。但是,子查询(和 CTE)需要它们,并且当您在同一个 FROM 子句中多次引用同一个表/视图时,SQL 编译器可以判断您在列中引用的是哪个表+列参考文献。
    【解决方案2】:

    我想你想要这样的东西:

    select Message_ID, Latitude, Longitude, MMSI, x.Ship_type, x.Vessel_name
    from table t
    outer apply (select Ship_type, Vessel_name from table x where x.MMSI=t.MMSI and x.Message_ID=5) x
    where t.Message_ID in (1,3) and (latitude > 55 and latitude < 85 and longitude > 50 and longitude < 141);
    

    【讨论】:

    • x 代表什么?
    • 是查询中OUTER APPLY部分的别名。
    【解决方案3】:
    with ship_cte(Ship_type,Vessel_name,MMSI)
    as(select Distinct Ship_type,Vessel_name,MMSI  from TableName WHERE Message_ID = 5)
    
    select b.Ship_type,b.Vessel_name,a.other_columns 
    from tableName a join ship_cte b on a.MMSI=b.MMSI
    WHERE (a.latitude > 55 and a.latitude < 85 and a.longitude > 50 and a.longitude < 141) 
    And (a.Message_ID = 1 or a.Message_ID = 3);
    

    在查询的第一部分中,我得到了 message_id=5 的所有行的 ship_type 和vessel_name,然后我根据 MMSI 编号将查询的这一部分与主表连接起来。

    【讨论】:

    • 除非表在 (MMSI, Message_ID) 上是唯一的,否则您将在 Join 上获得乘法。
    • 感谢@RBarryYoung 指出,我已编辑代码以仅考虑不同。
    • 好点,我认为 (Message_ID,MMSI) 在我的回答中也是独一无二的。 TOP(1) 无论如何都会解决它。
    • 我对 SQL Server 比较陌生,我不确定 ship_cte 来自哪里?
    • @dpalm with 子句定义了 CTE(公用表表达式),它只是一种子查询。 ship_cte 是别名,因为表子查询必须有别名,以便您以后可以引用它们的列。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多