Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何为数据库中的所有表返回变量的不同计数?_Sql_Sql Server - Fatal编程技术网

Sql 如何为数据库中的所有表返回变量的不同计数?

Sql 如何为数据库中的所有表返回变量的不同计数?,sql,sql-server,Sql,Sql Server,我有一个包含60多个表的SQL数据库,几乎所有表都填充了CLIENTID字段。我想计算每个表中唯一的客户端ID的数量 DECLARE @SQLQuery as nvarchar(max) = '' ------------------------------------ -- GET THE TABLES THAT HAVE A CLIENTID FROM SCHEMA SELECT @SQLQuery = @SQLQuery + qryTxt FROM ( SELECT DISTIN

我有一个包含60多个表的SQL数据库,几乎所有表都填充了CLIENTID字段。我想计算每个表中唯一的客户端ID的数量

DECLARE @SQLQuery as nvarchar(max) = ''

------------------------------------
-- GET THE TABLES THAT HAVE A CLIENTID FROM SCHEMA
SELECT @SQLQuery = @SQLQuery + qryTxt FROM (
    SELECT DISTINCT 'SELECT ''' + tables.name + ''', COUNT(DISTINCT CLIENTID) FROM ' + tables.name + ' UNION ' AS qryTxt
    FROM sys.columns left join sys.tables on columns.object_id = tables.object_id where columns.name = CLIENTID AND isnull(tables.name, '') <> '') subquery

------------------------------------
-- REMOVE THE LAST 'UNION' KEYWORD FROM SQLQUERY 
SET @SQLQuery = left(@sqlQuery, len(@sqlQuery) - 5)

------------------------------------
-- EXECUTE
execute sp_executesql @SQLQuery
我期待的结果是:

TABLE_NAME; CLIENTID_COUNT
dbo.HISTORY; 650
dbo.VISITS; 596
dbo.SALES; 1053
...; ...

这看起来应该很简单,但我已经玩了好几个小时的游标了,无法理解这一点。请帮忙

假设每个表中的列都是ClientId,您应该能够按原样使用它:

IF OBJECT_ID('tempdb..#temp_RESULTS') IS NOT NULL DROP TABLE #temp_RESULTS
CREATE TABLE #TEMP_RESULTS
(
TABLENAME VARCHAR(MAX),
CLIENTCNT BIGINT
)

DECLARE @TABLENAME VARCHAR(MAX)
DECLARE @command VARCHAR(MAX)

IF OBJECT_ID('tempdb..#temp_PROCESS') IS NOT NULL DROP TABLE #temp_PROCESS
SELECT * INTO #TEMP_PROCESS FROM sys.tables 

WHILE EXISTS(SELECT * FROM [#TEMP_PROCESS])
BEGIN
SET @TABLENAME = (SELECT TOP 1 [NAME] FROM [#TEMP_PROCESS])
SET @command = ('SELECT ''' + @TABLENAME + ''', COUNT(DISTINCT CLIENTID) AS CLIENTCNT FROM ' + @TABLENAME)
SELECT @command
INSERT INTO #TEMP_RESULTS
EXEC(@command) 

DELETE FROM [#TEMP_PROCESS] WHERE [NAME] = @TABLENAME
END

SELECT * FROM [#TEMP_RESULTS]
DROP TABLE IF EXISTS #clientId
CREATE TABLE #clientId
(
    TableName nvarchar(1000),
    ClientIdCount bigint
)

DECLARE @TableName nvarchar(1000);
DECLARE @CurrentQuery nvarchar(2000);

DECLARE result_cursor CURSOR local fast_forward FOR
SELECT DISTINCT
    '['+TABLE_SCHEMA + '].[' + TABLE_NAME + ']'
FROM
    INFORMATION_SCHEMA.COLUMNS
WHERE
    COLUMN_NAME = 'ClientId'

OPEN result_cursor
FETCH NEXT FROM result_cursor into @TableName
WHILE @@FETCH_STATUS = 0
BEGIN 

SET @CurrentQuery = 'SELECT ''' + @TableName + ''', COUNT(DISTINCT ClientId) FROM ' + @TableName
--print @CurrentQuery

INSERT INTO
    #clientId
(
    TableName,
    ClientIdCount
)
EXEC(@CurrentQuery)

FETCH NEXT FROM result_cursor into @TableName
END
--end loop

--clean up
CLOSE result_cursor
DEALLOCATE result_cursor

GO

SELECT
    *
FROM
    #clientId

您可以使用动态sql

这将通读您的系统表,找到那些具有ClientID列的表,并从每个表中构建一般形状为“Select CountDISTINCT ClientID”的查询文本

DECLARE @SQLQuery as nvarchar(max) = ''

------------------------------------
-- GET THE TABLES THAT HAVE A CLIENTID FROM SCHEMA
SELECT @SQLQuery = @SQLQuery + qryTxt FROM (
    SELECT DISTINCT 'SELECT ''' + tables.name + ''', COUNT(DISTINCT CLIENTID) FROM ' + tables.name + ' UNION ' AS qryTxt
    FROM sys.columns left join sys.tables on columns.object_id = tables.object_id where columns.name = CLIENTID AND isnull(tables.name, '') <> '') subquery

------------------------------------
-- REMOVE THE LAST 'UNION' KEYWORD FROM SQLQUERY 
SET @SQLQuery = left(@sqlQuery, len(@sqlQuery) - 5)

------------------------------------
-- EXECUTE
execute sp_executesql @SQLQuery

我真的不喜欢游标和循环。尽管从性能角度来看,这不会有太大区别,但我还是想分享一下如何利用系统表和动态sql来避免使用游标,而使用循环或临时表来实现类似的功能

要做到这一点,您需要的就是这些代码

declare @SQL nvarchar(max) = ''

select @SQL = @SQL + 'select TableName = ''' + t.name + ''', ClientID_Count = count(distinct clientID)
from ' + QUOTENAME(t.name) + ' UNION ALL ' 
from sys.tables t
join sys.columns c on c.object_id = t.object_id
where c.name = 'clientID'

select @SQL = left(@SQL, len(@SQL) - 10) --removes the last UNION ALL

select @SQL
--once your comfortable the dynamic sql is correct just uncomment the line below.
--exec sp_executesql @SQL

与这里的其他答案类似,但我会这样处理:

IF OBJECT_ID('#Tables', 'U') IS NOT NULL
    DROP TABLE #Tables;
SELECT ID = IDENTITY(INT, 1, 1),
    SchemaName = OBJECT_SCHEMA_NAME([object_id]),
    TableName = OBJECT_NAME([object_id]),
    ColumnName = name,
    DistinctCount = 0
    INTO #Tables
    FROM sys.columns
    WHERE name = 'CLIENTID';

DECLARE @ID INT = 1,
    @MaxID INT = (SELECT MAX(ID) FROM #Tables);
WHILE @ID < @MaxID
BEGIN;
    DECLARE @SQLCommand VARCHAR(MAX);
    SELECT @SQLCommand = FORMATMESSAGE('
UPDATE #Tables SET DistinctCount = (
    SELECT COUNT(DISTINCT %s) FROM %s.%s
    )
    WHERE ID = %i;',
        QUOTENAME(ColumnName), QUOTENAME(SchemaName), QUOTENAME(TableName), ID)
        FROM #Tables
        WHERE ID = @ID;
    EXEC (@SQLCommand);
    SET @ID += 1;
END;

SELECT *
    FROM #Tables;

你能分享你的代码和到目前为止得到的结果吗?基本上,有一些系统存储过程会列出所有的表。以此为基础,看看@IvanStarostinI的建议。我认为插入实际上应该是选择“++@TABLENAME+”,将distinct CLIENTID作为CLIENTCNT从“++@TABLENAME”中计数。我和你发布了非常相似的解决方案,相隔几秒钟呜!那是对我的赞美。