Два уровня группировки по одному набору данных. Является ли это возможным
Я выполняю запрос, который разбивает проценты по странам .. что-то вроде этого:
select country_of_risk_name, (sum(isnull(fund_weight,0)*100)) as 'FUND WEIGHT' from OFI_Country_Details WHERE FIXED_COMP_FUND_CODE = 'X' GROUP BY country_of_risk_name
Это возвращает мне правильный результат. Это может варьироваться от 1 страны до 100 стран. Как я могу написать свою логику о том, что она показывает мне 5 самых высоких процентов, а затем группирует всех тех, кто не входит в пятерку лучших, в категорию «Другие»? Пример вывода:
- США – 50%
- Канада – 10%
- Франция – 4%
- Испания – 2%
- Италия – 1,7%
- Другое – 25%
- Репликация SQL «Процесс не мог подключиться к подписчику»
- «Заявление не возвратило результирующий набор» при вызове процедуры из java
SELECT rn, CASE WHEN rn <= 5 THEN x.country_of_risk_name ELSE 'Other' END AS country_of_risk_name, SUM(x.[FUND WEIGHT]) AS SumPerc FROM( SELECT country_of_risk_name, CASE WHEN ROW_NUMBER() OVER(ORDER BY SUM(ISNULL(fund_weight,0)*100) DESC) <= 5 THEN ROW_NUMBER() OVER(ORDER BY SUM(ISNULL(fund_weight,0)*100) DESC) ELSE 6 END AS rn, SUM(ISNULL(fund_weight,0)*100) AS [FUND WEIGHT] FROM country_of_risk_name WHERE FIXED_COMP_FUND_CODE = 'X' GROUP BY country_of_risk_name ) x GROUP BY rn, CASE WHEN rn <= 5 THEN x.country_of_risk_name ELSE 'Other' END ORDER BY x.rn
См. Демонстрацию на SQLFiddle
Вот уродливый способ сделать это, используя только SQL:
select country, sum(perc) from ( select case when rn <= 5 then country else 'Other' end 'Country', case when rn <= 5 then rn else 6 end rn, perc from ( select *, row_number() over (order by perc desc) rn from yourresults ) t ) t group by country, rn order by rn
- Демо-версия SQL Fiddle
Я использовал yourresults
результаты в качестве результатов вашего вышеуказанного запроса – бросьте это в Common Table Expression
и вам должно быть хорошо идти:
with yourresults as ( select country_of_risk_name, (sum(isnull(fund_weight,0)*100)) as 'FUND WEIGHT' from OFI_Country_Details where FIXED_COMP_FUND_CODE = 'X' group by country_of_risk_name ) ...
Вот запрос с использованием CTE: также пример рабочего решения
;with TotalPercent(Country_Of_Risk_Name, Fund_Weight) as( select Country_Of_Risk_Name, sum(isnull(Fund_Weight, 0) * 100) Fund_Weight from OFI_Country_Details where FIXED_COMP_FUND_CODE = 'X' group by Country_Of_Risk_Name ), PercentWithRank(Country_Of_Risk_Name, Fund_Weight, RowNumber) as ( select Country_Of_Risk_Name, Fund_Weight, row_number() over (order by Fund_Weight desc) RowNumber from TotalPercent ) select Country_Of_Risk_Name, Fund_Weight from PercentWithRank where RowNumber <= 5 union all select 'Other', sum(Fund_Weight) Fund_Weight from PercentWithRank where RowNumber > 5
Попробуй это.
declare @country_of_risk_name as table (country varchar(100), FUND decimal(10,2)); insert into @country_of_risk_name values ('USA', 50), ('Canada', 10), ('France', 4), ('Spain', 2), ('Italy', 1.7), ('Other1', 1.5), ('Other2', 1.5), ('Other3', 1.5), ('Other4', 1.5), ('Other5', 1.5), ('Other6', 1.5); DECLARE @TBL AS TABLE(country_of_risk_name VARCHAR(100), FUND DECIMAL(18,2)) INSERT INTO @TBL SELECT TOP 5 country,SUM(FUND) FROM @country_of_risk_name group by country ORDER BY SUM(FUND) desc select * from @TBL UNION ALL select 'other', SUM(tbl1.fund) from @country_of_risk_name tbl1 left join @TBL tbl2 on tbl1.country =tbl2.country_of_risk_name where tbl2.country_of_risk_name is null