Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
Pleo Member Откуда: Сообщений: 3 |
Доброго времени суток! Недавно столкнулся с проблемой подсчета строк в некоторых видах таблиц. Допустим такая таблица: SELECT * FROM [Table]
Получить нужно таблицу:
То есть список суммарных(общих) полей и количество несуммарных под ними. Столбец Index - это порядковый номер, который важен при суммировании строк. Только так и определяется отношение суммарных полей к несуммарным полей. Столбец «Summary» показывает, является ли поле суммарным. Его значения либо 1, либо 0. Если есть суммарное поле, то в него должно что-то входить - т.е. не может быть такого:
Поменять структуру БД и конкретно этой таблицы, к сожалению, нельзя. Почему-то мне кажется, что решение простое, но дойти до него никак не могу. |
||||||||||||||||||||||||||||||||||||||||||||||||||
13 окт 14, 12:41 [16696127] Ответить | Цитировать Сообщить модератору |
Добрый Э - Эх
Guest |
Pleo, start_of_group |
13 окт 14, 12:44 [16696139] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104751 |
Что значит "под ним" По какому критерию Картофель и Огурец относятся к Овощ ? По Index ? |
||
13 окт 14, 12:44 [16696142] Ответить | Цитировать Сообщить модератору |
Владислав Колосов Member Откуда: Сообщений: 8350 |
Вероятно то, что имеет меньший Index и Summary = 0, относится к категории с 1. Но Index не должен быть меньше предыдущего. |
13 окт 14, 13:00 [16696250] Ответить | Цитировать Сообщить модератору |
Владислав Колосов Member Откуда: Сообщений: 8350 |
Т.е. все, что между категориями относится к наибольшей категории. |
13 окт 14, 13:01 [16696258] Ответить | Цитировать Сообщить модератору |
Добрый Э - Эх
Guest |
Pleo, Требуется SQL Server 2012 with t (Indx,Name,Summary) as ( select 99, 'Овощ', 1 union all select 101, 'Картофель', 0 union all select 102, 'Огурец', 0 union all select 196, 'Фрукт', 1 union all select 201, 'Яблоко', 0 union all select 250, 'Ягода', 1 union all select 253, 'Малина', 0 union all select 292, 'Клубника', 0 union all select 303, 'Рябина', 0 ) select name, cnt from ( select v0.*, count(1) over(partition by grp_id) - 1 as cnt from ( select t.*, sum(Summary) over(order by indx) as grp_id from t ) as v0 ) as v1 where Summary = 1 З.Ы. Посредством GROUP BY можно сократить один уровень вложенности. |
13 окт 14, 13:05 [16696290] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9646 |
with x as ( select t1.Name, t1.[Index] as s, isnull(t2.[Index], 2147483647) as e from [Table] t1 outer apply (select top (1) [Index] from [Table] where Summary = 1 and [Index] > t1.[Index] order by [Index]) t2 where t1.Summary = 1 ) select x.Name, count(*) from x join [Table] t on t.Summary = 0 and t.[Index] >= x.s and t.[Index] < x.e group by x.Name; |
13 окт 14, 13:14 [16696355] Ответить | Цитировать Сообщить модератору |
_djХомяГ
Guest |
------безотносительно версии сервака declare @t table ([index] int,name varchar(50),summ int) insert into @t select 99,'Овощ',1 union all select 101,'Картофель',0 union all select 102,'Огурец',0 union all select 196,'Фрукт',1 union all select 201,'Яблоко',0 union all select 202,'Ягода',1 union all select 204,'Черника',0 union all select 214,'Малина',0 union all select 215,'Волчья',0 select Category,count(*) from ( select *,((select top 1 name from @t t1 where t.[index]>=t1.[index] and t1.[summ]=1 order by [index] desc)) as Category from @t t ---order by [index] ) tmp where summ=0 group by Category |
13 окт 14, 13:20 [16696382] Ответить | Цитировать Сообщить модератору |
Добрый Э - Эх
Guest |
select max(case when Summary = 1 then name else '' end) as name, count(1) - 1 as cnt from ( select t.*, sum(Summary) over(order by indx) as grp_id from t ) as v0 group by grp_id |
||
13 окт 14, 13:21 [16696386] Ответить | Цитировать Сообщить модератору |
Pleo Member Откуда: Сообщений: 3 |
Спасибо большое всем, кто поучаствовал в решении проблемы.
Воспользовался твоим решением, потому что запрос будет использоваться на 2008 серваке.
Тебе тоже спасибо, но как я уже сказал сервак 2008. |
||||||
13 окт 14, 15:19 [16697331] Ответить | Цитировать Сообщить модератору |
_djХомяГ
Guest |
Так если сервак 2008 то все решения рабочие (если конечно база не в каком нибудь режиме "совместимости") |
13 окт 14, 15:31 [16697438] Ответить | Цитировать Сообщить модератору |
Добрый Э - Эх
Guest |
в 2008-м был лишь банальный sum()over(), без ORDER BY. А sum() over(ORDER BY) - с 2012 сервера, если мне память не изменяет. |
||
13 окт 14, 19:18 [16698905] Ответить | Цитировать Сообщить модератору |
vfalconwing Member Откуда: Сообщений: 3 |
Размазано в СТЕ для понимания, можно и сократить. Так сказать, по этапам. Для 2008 сервера ; with t (Indx, Name, Summary) as ( select 99, 'Овощ', 1 union all select 101, 'Картофель', 0 union all select 102, 'Огурец', 0 union all select 196, 'Фрукт', 1 union all select 201, 'Яблоко', 0 union all select 250, 'Ягода', 1 union all select 253, 'Малина', 0 union all select 292, 'Клубника', 0 union all select 303, 'Рябина', 0 ) , ss (Indx, Name, Summary, RNum) as ( SELECT Indx, Name, Summary , ROW_NUMBER() OVER ( ORDER BY t.Indx) AS RNum FROM t WHERE Summary = 1 ) , rr (Indx, NextInd, CatName, RNum, Name) AS ( SELECT ss.Indx , ISNULL(n.Indx, 999999) AS NextInd , ss.Name , ss.RNum , t.Name FROM ss LEFT JOIN ss n ON n.RNum = ss.RNum + 1 JOIN t ON t.Indx BETWEEN ss.Indx AND ISNULL(n.Indx, 999999) WHERE t.Summary = 0 ) SELECT Indx, NextInd, CatName, RNum , COUNT(rr.Name) AS Cnt FROM rr GROUP BY rr.Indx, rr.NextInd, rr.CatName, rr.RNum |
14 окт 14, 10:03 [16700384] Ответить | Цитировать Сообщить модератору |
_djХомяГ
Guest |
Да, точно ! |
||||
14 окт 14, 14:06 [16701956] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |