在SQL Server中联接多个表

时间:2018-07-28 10:30:38

标签: sql sql-server tsql join inner-join

我有一条select语句,该语句必须连接多个表,包括sys.indexessys.objectssys.schemassys.dm_db_index_physical_stats,以获得这样的表

enter image description here

这是声明:

select
    db_name() as [Database],
    sc.[name] as [Schema],
    obj.[name] as [Table],  
    idx.[type_desc] as [Index Type],
    idx.[name] as [Index Name],
    ips.[avg_fragmentation_in_percent] as [Fragmentation Percent]
from 
    sys.indexes as idx
inner join 
    sys.objects as obj on idx.object_id = obj.object_id
inner join 
    sys.schemas as sc  on obj.schema_id = sc.schema_id
inner join 
    sys.dm_db_index_physical_stats( NULL,NULL, NULL, NULL ,'LIMITED') AS ips on obj.object_id = ips.object_id 
where 
    idx.[name] is not null 
    and obj.[type] = 'u' or obj.[type] = 'v' 
order by 
    [Fragmentation Percent] desc

问题是该语句工作不正确,并且两次包含一些行(这样做像是交叉联接,但不完全是这样)。谁能指出我的错误?

感谢您的时间!

1 个答案:

答案 0 :(得分:3)

使用CROSS_APPLY代替INNER JOIN。这将允许您将相关值传递给表值函数。在此处将分区号添加到结果中:

SELECT
    db_name() as [Database],
    sc.[name] as [Schema],
    obj.[name] as [Table],  
    idx.[type_desc] as [Index Type],
    idx.[name] as [Index Name],
    ips.partition_number AS [Partition Number],
    ips.[avg_fragmentation_in_percent] as [Fragmentation Percent]
FROM sys.indexes as idx
INNER JOIN sys.objects as obj on idx.object_id = obj.object_id
INNER JOIN sys.schemas as sc  on obj.schema_id = sc.schema_id
CROSS APPLY sys.dm_db_index_physical_stats( DB_ID(), idx.object_id, idx.index_id, NULL ,'LIMITED') AS ips
ORDER BY [Fragmentation Percent] desc;

原始查询的错误是您没有在sys.dm_db_index_physical_stats的联接中包括index_id,并且没有为当前数据库中的对象过滤(相同的object_id可能存在于不同的数据库中)。 WHERE子句是多余的,因此我将其删除。

出于碎片整理的目的,应排除小索引,因为这些小索引是从混合盘区中分配的,即使重新构建,也会报告高碎片。