我有一个包含60多个表的SQL数据库,几乎所有表都填充有CLIENTID字段。我想计算每个表中唯一客户端ID的数量。
我正在寻找的结果是:
TABLE_NAME; CLIENTID_COUNT
dbo.HISTORY; 650
dbo.VISITS; 596
dbo.SALES; 1053
...; ...
这似乎应该很简单,但是我已经游玩了几个小时,无法弄清楚这个。请帮忙!
答案 0 :(得分:1)
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]
答案 1 :(得分:1)
假设该列在每个表中都完全是ClientId,那么您应该可以按原样使用它:
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
答案 2 :(得分:1)
您可以使用动态sql。
这将通读您的系统表,查找具有ClientID列的系统表,并从每个表中构建一般形状为“ Select Count(DISTINCT 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
答案 3 :(得分:1)
我真的不喜欢游标和循环。即使从性能的角度来看并不会有太大的不同,我还是想分享一下如何利用系统表和动态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
答案 4 :(得分:0)
与其他答案类似的模式,但这就是我要解决的方法:
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;