基于sys.tables的子查询表

时间:2017-04-28 14:39:27

标签: sql-server tsql

我正在尝试检索事实表中的所有主键,然后计算该事实表中按该id分组的记录数,但到目前为止,我似乎只能得到所有主键及其表。我想我需要做一些子查询

SELECT
tab1.name AS [FactTable],
col1.name AS [PrimaryKey]
FROM sys.indexes ind1
INNER JOIN sys.tables tab1
    ON tab1.object_id = ind1.object_id
INNER JOIN sys.schemas sch1
    ON tab1.schema_id = sch1.schema_id
INNER JOIN sys.columns col1
    ON col1.object_id = tab1.object_id AND col1.name like '%Id'     
WHERE tab1.name like 'Fact%' AND ind1.is_primary_key = 1

示例输出

primaryKey    countRecordsGroupedByPrimaryKey
2             4000
3             8343
4             203
1             4023

2 个答案:

答案 0 :(得分:0)

如果我正确理解了这个问题,你想根据一些标准计算某些表中的所有行。不确定为什么你关心主键部分,因为根据定义,主键必须是唯一的,所以这仍然可以简化为不检查主键但是无论如何。

我确实删除了对sys.columns的连接,因为除非您只想要名为Fact%的表并且有一个名为%Id的列,否则为什么它与列的名称有关。

根据我的理解,这应该让你非常接近。

declare @SQL nvarchar(max) = ''

select @SQL = @SQL + 'select TableName = ''' + tab1.name + ''', NumRows = count(*)  from ' + QUOTENAME(sch1.name) + '.' + QUOTENAME(tab1.name) + ' UNION ALL '
FROM sys.indexes ind1
INNER JOIN sys.tables tab1
    ON tab1.object_id = ind1.object_id
INNER JOIN sys.schemas sch1
    ON tab1.schema_id = sch1.schema_id
--INNER JOIN sys.columns col1
--    ON col1.object_id = tab1.object_id AND col1.name like '%Id'     
WHERE tab1.name like 'Fact%' 
    AND ind1.is_primary_key = 1


select @SQL = LEFT(@SQL, LEN(@SQL) - 10) + ' ORDER BY TableName'
select @SQL --uncomment the exec line below once you are comfortable that the dynamic sql is what you want.

--exec sp_executesql @SQL

答案 1 :(得分:0)

我走出困境,猜测你要计算事实表中使用的每个dimensionPK的数量。如果事实表引用了两个不同的维度,则需要两个不同的语句来计算该维度的使用情况。

对于下面的查询,请提供您的事实表名称和架构,它应该生成一个计数语句,用于连接您的事实,并通过连接键进行调暗和分组。
- 如果事实表有两种不同的FK关系,您将得到两种不同的陈述 - 如果表使用复合PK,则两个键列都将包含在连接

这很复杂,我没有任何有多个FK的桌子来测试它,所以请告诉我它是否符合你的要求。

DECLARE @NameOfTableWithFKs sysname = 'your fact table name',
        @SchemaOfTableWithFKs sysname = 'dbo';

WITH JoinColumns
AS (SELECT  QUOTENAME(OBJECT_SCHEMA_NAME(parent.object_id)) + '.' + QUOTENAME(OBJECT_NAME(parent.object_id)) AS ParentTableName,
            QUOTENAME(OBJECT_SCHEMA_NAME(referenced.object_id)) + '.' + QUOTENAME(OBJECT_NAME(referenced.object_id)) AS ReferencedTableName,
            QUOTENAME(OBJECT_NAME(parent.object_id)) + '.' + QUOTENAME(parent.name) + ' = ' + QUOTENAME(OBJECT_NAME(referenced.object_id)) + '.'
            + QUOTENAME(referenced.name) AS JoinColumn,
            QUOTENAME(OBJECT_NAME(referenced.object_id)) + '.' + QUOTENAME(referenced.name) AS GroupingColumn
    FROM    sys.foreign_key_columns AS fkc
      INNER JOIN sys.columns AS parent
        ON parent.object_id = fkc.parent_object_id
           AND  parent.column_id = fkc.parent_column_id
      INNER JOIN sys.columns AS referenced
        ON referenced.object_id = fkc.referenced_object_id
           AND  referenced.column_id = fkc.referenced_column_id
    WHERE   OBJECT_NAME(parent.object_id) = @NameOfTableWithFKs
            AND OBJECT_SCHEMA_NAME(parent.object_id) = @SchemaOfTableWithFKs
   ),
     JoinTables
AS (SELECT  QUOTENAME(OBJECT_SCHEMA_NAME(tbl.object_id)) + '.' + QUOTENAME(OBJECT_NAME(tbl.object_id)) AS ParentTableName,
            QUOTENAME(OBJECT_SCHEMA_NAME(rtbl.object_id)) + '.' + QUOTENAME(OBJECT_NAME(rtbl.object_id)) AS ReferencedTableName
    FROM    sys.tables AS tbl
      INNER JOIN sys.foreign_keys AS cstr
        ON cstr.parent_object_id = tbl.object_id
      INNER JOIN sys.tables AS rtbl
        ON rtbl.object_id = cstr.referenced_object_id
    WHERE   OBJECT_NAME(tbl.object_id) = @NameOfTableWithFKs
            AND OBJECT_SCHEMA_NAME(tbl.object_id) = @SchemaOfTableWithFKs
   )
SELECT  'SELECT Count(*)' + ( SELECT    ', ' + JC.GroupingColumn
                              FROM  JoinColumns AS JC
                              WHERE JC.ParentTableName = jt.ParentTableName
                                    AND JC.ReferencedTableName = jt.ReferencedTableName
                              FOR XML PATH('')
                            ) + ' FROM ' + JT.ParentTableName + ' INNER JOIN ' + JT.ReferencedTableName + ' ON'
        + SUBSTRING(( SELECT    ' AND ' + JC.JoinColumn
                      FROM  JoinColumns AS JC
                      WHERE   JC.ParentTableName = JT.ParentTableName
                              AND JC.ReferencedTableName = JT.ReferencedTableName
                      FOR XML PATH('')
                    ), 5, 8000
                   ) + ' GROUP BY ' + SUBSTRING(( SELECT    ', ' + JC.GroupingColumn
                                                  FROM      JoinColumns AS JC
                                                  WHERE  JC.ParentTableName = JT.ParentTableName
                                                         AND JC.ReferencedTableName = JT.ReferencedTableName
                                                  FOR XML PATH('')
                                                ), 2, 8000
                                               )
FROM    JoinTables AS JT;