繁体   English   中英

在SQL表上创建统计信息之前,请检查是否存在具有相同列的统计信息

[英]Check the existence of statistic with same columns before creating a statistic on a SQL table

我需要在具有不同列组合的表上创建一些统计信息。 但是可能已经存在一些具有相同列组合的统计数据。 因此,在创建具有列组合的统计信息之前,我想检查是否存在具有相同列组合的任何统计信息。 如果存在,那么我将不会创建统计信息,如果不存在,那么只有我将创建统计信息。

例如,在此表上创建一个表和统计信息,如下所示:

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])

请参阅后面的统计信息是第一个统计信息的副本(使用相同的列)。

因此,为了避免重复,我需要检查是否存在具有相同列的任何统计信息。

有没有办法做到这一点?

请帮忙

以下查询将检查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;

为上面更新了SQLFiddle

以下查询将给出具有给定列组合的统计信息的名称(如果存在)。

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

为上面更新了SQLFiddle

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM