计算特定列和列值的所有表的行

时间:2015-07-21 06:12:06

标签: sql sql-server sql-server-2008

我正在使用SQL Server 2008,并希望从数据库中的所有表中获取列的总行数。

这是我的样本数据

表1

T1Id       Name
1          XCV
2          ASD
3          GHJ

表2

  T2Id      T1Id       Name
  1         1          TYU
  2         1          BBB
  3         2          LLL
  4         1          JJJ
  5         1          LKM
  6         2          POI

表3

  T3Id      T1Id       Name
  1         3          DDS
  2         3          BSS
  3         2          SQA
  4         2          FWF
  5         1          IKM
  6         2          PLO

我也有Table4,但不想添加结果计数

我正在尝试

    SELECT     TOP (100) PERCENT ta.name AS TableName, SUM(pa.rows) AS RowCnt
FROM         sys.tables AS ta LEFT OUTER JOIN
                      sys.partitions AS pa ON pa.object_id = ta.object_id LEFT OUTER JOIN
                      sys.schemas AS sc ON ta.schema_id = sc.schema_id LEFT OUTER JOIN
                      INFORMATION_SCHEMA.COLUMNS ON ta.name = INFORMATION_SCHEMA.COLUMNS.TABLE_NAME
WHERE     (ta.is_ms_shipped = 0) AND (pa.index_id IN (1, 0)) AND (INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME = N'T1Id') AND 
                      (ta.name <> N'Table4')
GROUP BY sc.name, ta.name
HAVING      (SUM(pa.rows) > 0)
ORDER BY RowCnt DESC

以上SQL给我结果

 TableName    RowCnt
 XCV          5
 ASD          5
 GHJ          2

但我想只获得XCV(Table1和T1Id = 1)记录计数。 如何使用上述查询或任何其他建议?

预期结果

 Name    RCount
 XCV     5

编辑:

我的数据库中有超过200个表,并且所有表中都有T1Id, 我的目标是从所有表中找到T1Id = 1的计数,我不想在结果中包含表4.

1 个答案:

答案 0 :(得分:1)

您似乎希望“通常”在名为T1Id的任何表格列中找到值为1的所有值(Table4除外),我想您会想要排除Table1行计数,因为这似乎是列值名称映射的'主'参考表)。

AFAIK您需要使用动态Sql才能应用过滤器。

不幸的是your sample query会产生误导 - 查询实际上会返回

Table2  6
Table3  6
Table1  3

sys.partitions.rows获得的表的整体行数是多少(即未进行过滤)。

我认为所需的方法是,在找到包含感兴趣的列的“合格”表后,您需要做的是实际查询每个表,然后使用所需的谓词过滤每个表(即T1ID = '1' )。然后,您需要总结所有这些结果以预测最终结果。

我的解决方案太糟糕了,无法考虑在此发布,但我已经在Fiddle here上提出了Gist Here。基本上,它生成以下动态Sql:

WITH summedCte AS 
( 
    SELECT T1ID, COUNT(*) AS RowInTable  FROM [dbo].[Table2] GROUP BY T1ID  
    UNION ALL  
    SELECT T1ID, COUNT(*) AS RowInTable  FROM [dbo].[Table3] GROUP BY T1ID 
)
SELECT T.Name, t.T1Id, SUM(c.RowInTable) AS RowsInAllTables
    FROM summedCte c
    INNER JOIN Table1 t
      on c.T1Id = t.T1Id
    WHERE t.Name = 'XCV'
    GROUP BY t.Name, t.T1Id;

您可以明显地根据自己的谓词需求进行定制。

编辑 - 警告

在看到OP的评论后,即预期的用法是在应用程序中强制执行“如果在父行中使用可能不会删除”业务规则,很明显使用游标和循环不适合生产

首选方法应该与ORM或其他生产力工具一致:

  • 使用动态sql hack构建基于CTE的查询(即代替sp_executesql @sql,只需打印@sql并获取结果SQL)
  • 然后可以将生成的CTE(约200个表的UNION)烘焙到您的应用程序中以强制执行业务规则。
  • 但是,每次更改任何相关数据库DDL时,都需要重新生成CTE并将其重新吸收到应用程序中,例如可以避免构建,例如将CTE查询保留为标记化脚本。