2013-08-11 3 views
1

Можно ли суммировать два значения, которые исходят от COUNT(DISTINCT [something])? У меня есть таблица, в которой есть около 400 миллионов записей. Эта таблица увеличивается в зависимости от посещений пользователей , и теперь я хочу получить базы COUNT(DISTINCT [SpecialUser]) по обычным запросам, для ответа на запрос требуется около 5-6 минут. Теперь я думал, если это возможно:Sql Sum of Distinct

Сохранить ответ от Вчерашнего COUNT(DISTINCT [SpecialUser]), назови его total и затем просуммировать его с сегодняшним результатом увеличения скорости запросов? Я знаю, что это невозможно в обычном режиме из-за Distinct, но есть ли другое решение для этого?

Для справки, вот полный запрос:

DECLARE @Total_User int 

SELECT @Total_User = COUNT(DISTINCT [SpecialUser]) 
FROM [dbo].[Visit] AS V 
WHERE 
    LEN([SpecialUser]) > 1 

UPDATE [dbo].[Stat] 
SET [email protected]_User 
WHERE ID = 1; 
+0

@nyzm: Хороший улов, однако, .NET поддерживает многие РСУБД. –

+0

@nooob change your avatar man .. проверьте ответ ниже и попробуйте узнать больше. – woofmeow

+0

@nooob: у вас есть всего 400M строк. Но сколько уникальных пользователей у вас в этой таблице? Я имею в виду результат 'SELECT count (пользователь DISTINCT) ...'? – mvp

ответ

1

Очевидно, ваша проблема заключается в структуре схемы базы данных/таблицы.

Я считаю, что каждый раз, когда пользователь посещается, новая запись добавляется в таблицу. Тем не менее, вы должны получить все отдельные поля SpecialUser, которые представляют собой различную информацию, чем в вашей таблице.

Решение должно записывать эту информацию в другой таблице (или использовать тот, который у вас уже есть). В этой таблице должно быть есть эти уникальные значения с уникальными ключами.

Однако, если это невозможно прямо сейчас из-за ... чего-то, лучшего решения, которое я могу запомнить сейчас (и того, которое избегает печально известных показателей varchar), является добавление вычисленного столбца в вашу таблицу, индексируйте его и используйте его в своем запросе.

Это должно выглядеть примерно так:

IsSpecialUser = CASE WHEN LEN([SpecialUser]) > 1 THEN 1 ELSE 0 END 

Полный DDL:

ALTER TABLE dbo.Visit 
ADD IsSpecialUser AS (CASE WHEN LEN([SpecialUser]) > 1 THEN 1 ELSE 0 END) PERSISTED 
GO 

После этого, создать индекс dbo.Visit.IsSpecialUser. Ваш запрос должен выглядеть так:

SELECT @Total_User = COUNT(DISTINCT [SpecialUser]) 
FROM [dbo].[Visit] AS V 
WHERE IsSpecialUser = 1 
+0

О, я думаю, что делать трюки, но его на время запроса времени, чтобы изменить таблицу, я думаю. им будет проверять его на резервном db! спасибо человеку –

0

магазин значение в другой таблице на разные дни. В противном случае это займет примерно примерно столько времени, как вы сказали.

Это может быть немного оптимизировано, но это не так сильно по сравнению с 5-6 минутами. Я предполагаю, что вам нужно что-то быстрее, чем это. Вы можете попробовать использовать что-то вроде query cache, если вам неудобно хранить номер в вашей базе данных.

Нижняя линия: вы не можете ускорить работу встроенных функций sql.

Надежда, что помогает :)

+0

Ive сделали это на других полях, как это: 'DECLARE @LastupdateTime Datetime DECLARE @TotalVisit BIGINT DECLARE @LastTotalVisit BIGINT DECLARE @NewTotalVisit BIGINT ВЫБРАТЬ @ LastupdateTime = UpdateDate from [dbo]. [Stat] SELECT @ LastTotalVisit = TotalNewsVisit from [dbo]. [Stat] SELECT @ TotalVisit = Count (*) From Visit WHERE [VisitDate]> = @LastupdateTime set @NewTotalVisit = @TotalVisit + @LastTotalVisit UPDATE [dbo]. [Stat] SET TotalNewsVisit = @ NewTotalVisit WHERE ID = 1; ' этот запрос ускоряет скорость около 5 минут на этом столе. грустно это работает только на поле без отдельного :( –