Tsql 字符字段中前3位值的百分比
我有一个不寻常的情况。请考虑以下代码:Tsql 字符字段中前3位值的百分比,tsql,sql-server-2005,window-functions,Tsql,Sql Server 2005,Window Functions,我有一个不寻常的情况。请考虑以下代码: IF OBJECT_ID('tempdb..#CharacterTest') IS NOT NULL DROP TABLE #CharacterTest CREATE TABLE #CharacterTest ( [ID] int IDENTITY(1, 1) NOT NULL, [CharField] varchar(50) NULL ) INSERT INTO #CharacterTest (CharField) VALUES (
IF OBJECT_ID('tempdb..#CharacterTest') IS NOT NULL
DROP TABLE #CharacterTest
CREATE TABLE #CharacterTest
(
[ID] int IDENTITY(1, 1) NOT NULL,
[CharField] varchar(50) NULL
)
INSERT INTO #CharacterTest (CharField)
VALUES ('A')
, ('A')
, ('A')
, ('A')
, ('B')
, ('B')
, ('B')
, ('C')
, ('C')
, ('D')
, ('D')
, ('F')
, ('G')
, ('H')
, ('I')
, ('J')
, ('K')
, ('L')
, ('M')
, ('N')
, (' ')
, (' ')
, (' ')
, (NULL)
, ('');
我想要一个查询,它给我一个字符串,如下所示:
A 16%,B 12%,C8%
请注意以下事项:
我不希望在前三名中列出空字符串、带所有空格的字符串或空字符串,但我希望使用表的整个记录计数计算值的百分比。
可以忽略关系,因此如果列表中有22个值的频率为8%,则可以简单地返回第一个值。
百分比可以四舍五入为整数。
我希望找到编写此查询的最简单方法,同时仍保持T-SQL与SQLServer2005的兼容性。最好的方法是什么?窗口功能 我的第一次尝试可能是这样。不是说这是最好的处理方法,而是说它会起作用
DECLARE @TotalCount INT
SELECT @TotalCount = COUNT(*) FROM #CharacterTest AS ct
SELECT TOP(3) CharField, COUNT(*) * 1.0 / @TotalCount AS OverallPercentage
FROM #CharacterTest AS ct
WHERE CharField IS NOT NULL AND REPLACE(CharField, ' ', '') <> ''
GROUP BY CharField
ORDER BY COUNT(*) desc
DROP TABLE #CharacterTest
我的第一次尝试可能是这样。不是说这是最好的处理方法,而是说它会起作用
DECLARE @TotalCount INT
SELECT @TotalCount = COUNT(*) FROM #CharacterTest AS ct
SELECT TOP(3) CharField, COUNT(*) * 1.0 / @TotalCount AS OverallPercentage
FROM #CharacterTest AS ct
WHERE CharField IS NOT NULL AND REPLACE(CharField, ' ', '') <> ''
GROUP BY CharField
ORDER BY COUNT(*) desc
DROP TABLE #CharacterTest
这将获得所需的字符串:
declare @output varchar(200);
with cte as (
select CharField
, (count(*) * 100) / (select count(*) from #CharacterTest) as CharPct
, row_number() over (order by count(*) desc, CharField) as RowNum
from #CharacterTest
where replace(CharField, ' ', '') not like ''
group by CharField
)
select @output = coalesce(@output + ', ', '') + CharField + ' (' + cast(CharPct as varchar(11)) + '%)'
from cte
where RowNum <= 3
order by RowNum;
select @output;
-- Returns:
-- A (16%), B (12%), C (8%)
不过,我想提醒大家注意在varchar50列中存储一个字符。这将获得您需要的字符串:
declare @output varchar(200);
with cte as (
select CharField
, (count(*) * 100) / (select count(*) from #CharacterTest) as CharPct
, row_number() over (order by count(*) desc, CharField) as RowNum
from #CharacterTest
where replace(CharField, ' ', '') not like ''
group by CharField
)
select @output = coalesce(@output + ', ', '') + CharField + ' (' + cast(CharPct as varchar(11)) + '%)'
from cte
where RowNum <= 3
order by RowNum;
select @output;
-- Returns:
-- A (16%), B (12%), C (8%)
不过,我想提醒大家注意在varchar50列中存储一个字符。我会选择
WITH T1
AS (SELECT [CharField],
100.0 * COUNT(*) OVER (PARTITION BY [CharField]) /
COUNT(*) OVER () AS Pct
FROM #CharacterTest),
T2
AS (SELECT DISTINCT TOP 3 *
FROM T1
WHERE [CharField] <> '' --Excludes all blank or NULL as well
ORDER BY Pct DESC)
SELECT STUFF((SELECT ',' + [CharField] + ' (' + CAST(CAST(ROUND(Pct,1) AS INT) AS VARCHAR(3)) + ')'
FROM T2
ORDER BY Pct DESC
FOR XML PATH('')), 1, 1, '') AS Result
我会去的
WITH T1
AS (SELECT [CharField],
100.0 * COUNT(*) OVER (PARTITION BY [CharField]) /
COUNT(*) OVER () AS Pct
FROM #CharacterTest),
T2
AS (SELECT DISTINCT TOP 3 *
FROM T1
WHERE [CharField] <> '' --Excludes all blank or NULL as well
ORDER BY Pct DESC)
SELECT STUFF((SELECT ',' + [CharField] + ' (' + CAST(CAST(ROUND(Pct,1) AS INT) AS VARCHAR(3)) + ')'
FROM T2
ORDER BY Pct DESC
FOR XML PATH('')), 1, 1, '') AS Result
在我的盒子上没有变量和比我的头发快的头发…尼斯在我的盒子上没有变量和比我的头发快的头发…尼斯