Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Подсчет строк  [new]
Pleo
Member

Откуда:
Сообщений: 3
Доброго времени суток!
Недавно столкнулся с проблемой подсчета строк в некоторых видах таблиц.
Допустим такая таблица:
SELECT * FROM [Table]

IndexNameSummary
99Овощ1
101Картофель0
102Огурец0
196Фрукт1
201Яблоко0
250Ягода1
253Малина0
292Клубника0
303Рябина0


Получить нужно таблицу:

NameCounts
Овощ2
Фрукт1
Ягода3

То есть список суммарных(общих) полей и количество несуммарных под ними.


Столбец Index - это порядковый номер, который важен при суммировании строк. Только так и определяется отношение суммарных полей к несуммарным полей.
Столбец «Summary» показывает, является ли поле суммарным. Его значения либо 1, либо 0.
Если есть суммарное поле, то в него должно что-то входить - т.е. не может быть такого:
IndexNameSummary
99Овощ1
196Фрукт1

Поменять структуру БД и конкретно этой таблицы, к сожалению, нельзя.

Почему-то мне кажется, что решение простое, но дойти до него никак не могу.
13 окт 14, 12:41    [16696127]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
Добрый Э - Эх
Guest
Pleo,

start_of_group
13 окт 14, 12:44    [16696139]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
Glory
Member

Откуда:
Сообщений: 104751
Pleo
То есть список суммарных(общих) полей и количество несуммарных под ними.

Что значит "под ним"
По какому критерию Картофель и Огурец относятся к Овощ ? По Index ?
13 окт 14, 12:44    [16696142]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8350
Вероятно то, что имеет меньший Index и Summary = 0, относится к категории с 1. Но Index не должен быть меньше предыдущего.
13 окт 14, 13:00    [16696250]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8350
Т.е. все, что между категориями относится к наибольшей категории.
13 окт 14, 13:01    [16696258]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
Добрый Э - Эх
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]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
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]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
_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]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
Добрый Э - Эх
Guest
Добрый Э - Эх
З.Ы.
Посредством GROUP BY можно сократить один уровень вложенности.
Укороченный вариант:
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]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
Pleo
Member

Откуда:
Сообщений: 3
Спасибо большое всем, кто поучаствовал в решении проблемы.
_djХомяГ
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

Воспользовался твоим решением, потому что запрос будет использоваться на 2008 серваке.

Добрый Э - Эх
Добрый Э - Эх
З.Ы.
Посредством GROUP BY можно сократить один уровень вложенности.
Укороченный вариант:
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

Тебе тоже спасибо, но как я уже сказал сервак 2008.
13 окт 14, 15:19    [16697331]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
_djХомяГ
Guest
Так если сервак 2008 то все решения рабочие (если конечно база не в каком нибудь режиме "совместимости")
13 окт 14, 15:31    [16697438]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
Добрый Э - Эх
Guest
_djХомяГ
Так если сервак 2008 то все решения рабочие (если конечно база не в каком нибудь режиме "совместимости")

в 2008-м был лишь банальный sum()over(), без ORDER BY. А sum() over(ORDER BY) - с 2012 сервера, если мне память не изменяет.
13 окт 14, 19:18    [16698905]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
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]     Ответить | Цитировать Сообщить модератору
 Re: Подсчет строк  [new]
_djХомяГ
Guest
Добрый Э - Эх
_djХомяГ
Так если сервак 2008 то все решения рабочие (если конечно база не в каком нибудь режиме "совместимости")

в 2008-м был лишь банальный sum()over(), без ORDER BY. А sum() over(ORDER BY) - с 2012 сервера, если мне память не изменяет.

Да, точно !
14 окт 14, 14:06    [16701956]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить