У меня есть следующая таблица и данные в SQL Server 2005:
create table LogEntries (
ID int identity,
LogEntry varchar(100)
)
insert into LogEntries values ('beans')
insert into LogEntries values ('beans')
insert into LogEntries values ('beans')
insert into LogEntries values ('cabbage')
insert into LogEntries values ('cabbage')
insert into LogEntries values ('beans')
insert into LogEntries values ('beans')
Я хотел бы сгруппировать повторяющиеся записи журнала, чтобы получить следующие результаты:
LogEntry EntryCount
beans 3
cabbage 2
beans 2
Можете ли вы придумать какой-либо способ сделать это в TSQL, помимо использования курсора?


SQL не совсем моя сильная сторона, но не буду
SELECT LogEntry, COUNT(1) AS Counter FROM LogEntries GROUP BY LogEntry
сделай это?
Ах, в медвежью яму тоже упал. Ну что ж. По крайней мере, я в хорошей компании :)
Не думаю, что это можно сделать одним запросом. Чтобы обеспечить количество в запросе, вам необходимо сгруппировать, используя столбец LogEntry. Однако это даст вам только общее количество записей в LogEntry, а не количество записей в последовательности, которые вы ищете. Я думаю, что вызывается курсор (или переносите весь набор данных в ваше приложение и используйте там логику для получения желаемых результатов).
Если мой мозг еще не загрузился сегодня утром
SELECT
LogEntry, COUNT(LogEntry) as EntryCount
FROM
LogEntries
GROUP BY
LogEntry
Нет, это приведет к бобам - 5 Кочанная капуста - 2
Теперь я достаточно внимательно посмотрел на реальный вопрос :-)
Хм, при пересмотре, почему бы просто не использовать курсор? Производительность не всегда хуже, чем у обычного SQL - и другим людям наверняка будет легко следовать коду, когда они придут посмотреть на него. Оберните его в сохраненный процесс или функцию, и вы сможете использовать его практически везде, где вам может понадобиться.
Это комплексное решение проблемы. Спектакль, наверное, отстой, но работает :)
CREATE TABLE #LogEntries (
ID INT IDENTITY,
LogEntry VARCHAR(100)
)
INSERT INTO #LogEntries VALUES ('beans')
INSERT INTO #LogEntries VALUES ('beans')
INSERT INTO #LogEntries VALUES ('beans')
INSERT INTO #LogEntries VALUES ('cabbage')
INSERT INTO #LogEntries VALUES ('cabbage')
INSERT INTO #LogEntries VALUES ('carrots')
INSERT INTO #LogEntries VALUES ('beans')
INSERT INTO #LogEntries VALUES ('beans')
INSERT INTO #LogEntries VALUES ('carrots')
SELECT logentry, COUNT(*) FROM (
SELECT logentry,
ISNULL((SELECT MAX(id) FROM #logentries l2 WHERE l1.logentry<>l2.logentry AND l2.id < l1.id), 0) AS id
FROM #LogEntries l1
) AS a
GROUP BY logentry, id
DROP TABLE #logentries
Полученные результаты:
beans 3
cabbage 2
carrots 1
beans 2
carrots 1
ISNULL () требуется для первого набора компонентов.
Блестяще! Спасибо, это намного проще, чем курсор, который я написал.
Я тоже схожу с ума, так как сейчас я смотрю на это, я сам использовал такого рода решения на основе наборов в прошлом.
Я думаю, это сработает ... хотя не слишком тщательно проверял
select
COUNT(*),subq.LogEntry
from
(
select
ROW_NUMBER() OVER(ORDER BY id)-ROW_NUMBER() OVER(PARTITION BY logentry ORDER BY id) as t,*
from
LogEntries
) subq
group by
subq.t,subq.LogEntry
order by
MIN(subq.ID)
Спасибо, работает. Раньше я не использовал ключевое слово partition. Это интересно.
Это очень элегантное и хитрое использование функции OVER (). Хороший!
АККУРАТНЫЙ! Я недостаточно хорошо разбираюсь в партиционировании ... подойдет!
Нет, это приведет к бобам - 5 Кочанная капуста - 2