SQL Server 2008 复杂查询和表连接

Posted

技术标签:

【中文标题】SQL Server 2008 复杂查询和表连接【英文标题】:SQL Server 2008 Complex Query & Table Join 【发布时间】: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

【问题讨论】:

【参考方案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 是别名,因为表子查询必须有别名,以便您以后可以引用它们的列。

以上是关于SQL Server 2008 复杂查询和表连接的主要内容,如果未能解决你的问题,请参考以下文章

多个连接子查询 SQL Server 2008

SQL Server 2008 - 连接导致性能下降

当有更多行或查询变得更复杂时,分区视图会读取所有表? SQL Server 2008 错误?

如何在 SQL Server 2008 中查看打开的连接/正在运行的查询? [复制]

Sql Server2008温故而知新系列01:库和表的创建及删除

sqlserver 数据库表数据合并