You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过SQL Server数据库元数据查询表列的基数(唯一值数量)

通过SQL Server元数据获取列基数的查询语句

你需要的是不直接扫描目标表,仅通过系统元数据获取表列不同值数量(基数)的SQL Server查询,以下是基于系统统计信息的实现方案:

核心思路

SQL Server会自动维护表的统计信息(用于查询优化),这些统计信息包含列的不同值估算数据。我们可以通过sys.stats、sys.stats_columns、sys.columns等系统视图,结合统计信息的密度值或直方图数据计算列基数,无需直接查询目标表。

实现语句(估算值)

方式1:利用统计信息密度计算

DECLARE @TableName NVARCHAR(128) = N'tablename';
DECLARE @SchemaName NVARCHAR(128) = N'dbo'; -- 按需修改架构名

SELECT
    c.name AS ColumnName,
    -- 基数 = 表总行数 / 统计密度(密度为1/基数,适用于主键、索引列的统计信息)
    CASE 
        WHEN s.stats_id = 1 THEN CAST(sp.rows / s.density AS BIGINT)
        -- 非索引列统计,通过直方图的distinct键数量估算
        ELSE (SELECT COUNT(DISTINCT range_hi_key) FROM sys.dm_db_stats_histogram(s.object_id, s.stats_id))
    END AS EstimatedCardinality,
    sp.rows AS TotalTableRows
FROM sys.columns c
JOIN sys.stats_columns sc ON c.object_id = sc.object_id AND c.column_id = sc.column_id
JOIN sys.stats s ON sc.object_id = s.object_id AND sc.stats_id = s.stats_id
JOIN sys.tables t ON c.object_id = t.object_id
JOIN sys.schemas sch ON t.schema_id = sch.schema_id
JOIN sys.partitions sp ON t.object_id = sp.object_id AND sp.index_id < 2
WHERE
    t.name = @TableName
    AND sch.name = @SchemaName
GROUP BY
    c.name, s.stats_id, s.density, sp.rows
ORDER BY
    c.name;

方式2:动态SQL遍历列的统计直方图

如果需要更统一的估算逻辑,可用动态SQL处理每个列的统计信息:

DECLARE @TableName NVARCHAR(128) = N'tablename';
DECLARE @SchemaName NVARCHAR(128) = N'dbo';
DECLARE @SQL NVARCHAR(MAX) = N'';

SELECT @SQL += N'
SELECT 
    ''' + c.name + N''' AS ColumnName,
    (SELECT COUNT(DISTINCT range_hi_key) FROM sys.dm_db_stats_histogram(OBJECT_ID(N''' + QUOTENAME(sch.name) + N'.' + QUOTENAME(t.name) + N'''), ' + CAST(s.stats_id AS NVARCHAR) + N''')) AS EstimatedCardinality,
    (SELECT SUM(rows) FROM sys.partitions WHERE object_id = OBJECT_ID(N''' + QUOTENAME(sch.name) + N'.' + QUOTENAME(t.name) + N''') AND index_id < 2) AS TotalTableRows
UNION ALL'
FROM sys.columns c
JOIN sys.stats_columns sc ON c.object_id = sc.object_id AND c.column_id = sc.column_id
JOIN sys.stats s ON sc.object_id = s.object_id AND sc.stats_id = s.stats_id
JOIN sys.tables t ON c.object_id = t.object_id
JOIN sys.schemas sch ON t.schema_id = sch.schema_id
WHERE
    t.name = @TableName
    AND sch.name = @SchemaName;

-- 移除末尾多余的UNION ALL
SET @SQL = LEFT(@SQL, LEN(@SQL) - 10);

EXEC sp_executesql @SQL;

注意事项

  • 结果为估算值:统计信息基于抽样更新,若统计信息过时(比如表数据大幅变更后未更新统计),结果会有偏差,可手动执行UPDATE STATISTICS [schema.tablename]更新统计。
  • 无统计信息的列:如果列从未被查询过,可能没有统计信息,此时需要手动创建统计信息:CREATE STATISTICS Stats_ColumnName ON [schema.tablename](ColumnName);。
  • 精确值限制:若必须获取精确的不同值数量,无法绕过直接查询目标表的操作,因为元数据中不存在精确的实时基数数据。

内容的提问来源于stack exchange,提问作者Nithya M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 11:22:13