我需要在具有不同列组合的表上创建一些统计信息。但是,对于相同的列组合,可能已经存在一些统计信息。因此,在创建具有列组合的统计信息之前,我想检查是否存在具有相同列组合的统计信息。如果存在,那么我将不创建统计信息;如果不存在,则仅我将创建统计信息。
例如,如下创建一个表和该表的统计信息:
CREATE TABLE Gift
(
Gift_Id INTEGER IDENTITY (1,1) PRIMARY KEY,
Person_Id INTEGER,
Event_Id INTEGER,
Agent_Id INTEGER,
Fund_Id INTEGER,
Amount FLOAT
)
CREATE STATISTICS [Stats1_1_2_3]
ON [dbo].[Gift]([Gift_Id], [Person_Id], [Event_Id])
因此,我们有一个表Gift
和一个统计信息,其中包含Gift_ID,Person_Id和Event_Id列。
现在,如果我创建另一个统计数据如下:
CREATE STATISTICS [Stats2_1_2_3]
ON [dbo].[Gift]([Gift_Id], [Person_Id], [Event_Id])
请参阅稍后的统计信息与第一个统计信息重复(具有相同的列)。
因此,为避免重复,我需要检查是否存在具有相同列的统计信息。
有什么办法吗?
请帮助
答案 0 :(得分:2)
以下查询将检查sys.stats,sys.stats_columns和sys.columns表,以查找给定表的所有统计信息,并获取每个统计信息的每一列。
分组和计数是为了检查是否存在引用所有列的统计信息。
请注意,查询中明确提到了表名,列名和要检查的列数。
更新后的查询还将检查是否仅存在列出的列(计数= 3)和列出的所有列(计数3 = 3)。用于其他统计信息将涉及CASE语句的修改以及WHERE最后一行中的“ 3”值。
SELECT * FROM (
SELECT s.name AS statistics_name,
count(*) as counting,
sum(case
when c.name = 'Gift_Id' then 1
when c.name = 'Person_Id' then 1
when c.name = 'Event_Id' then 1
else 0
end) as counting3
FROM sys.stats AS s
INNER JOIN sys.stats_columns AS sc
ON s.object_id = sc.object_id AND s.stats_id = sc.stats_id
INNER JOIN sys.columns AS c
ON sc.object_id = c.object_id AND c.column_id = sc.column_id
WHERE s.object_id = OBJECT_ID('Gift')
Group by s.name) T
WHERE T.COUNTING = 3 AND T.COUNTING3 = 3;
答案 1 :(得分:1)
以下查询将使用给定的列组合给出统计信息的名称(如果存在)。
SELECT s.name
FROM sys.stats s inner join
sys.stats_columns sc on s.stats_id = sc.stats_id and s.object_id = sc.object_id
JOIN sys.columns c ON c.[object_id] = sc.[object_id] AND c.column_id = sc.column_id
WHERE OBJECT_NAME(s.OBJECT_ID) = 'Gift'
and s.stats_id not in
(
SELECT distinct s.stats_id
FROM sys.stats s inner join
sys.stats_columns sc on s.stats_id = sc.stats_id and s.object_id = sc.object_id
JOIN sys.columns c ON c.[object_id] = sc.[object_id] AND c.column_id = sc.column_id
WHERE OBJECT_NAME(s.OBJECT_ID) = 'Gift' and c.name not in ('Gift_Id','Person_Id','Event_Id')
)
group by s.name
having count(1)= 3