SQL Server: как выбрать фиксированное количество строк (выбрать каждое x-е значение) - PullRequest
4 голосов
/ 20 марта 2012

Краткое описание: у меня есть таблица с данными, которые обновляются за определенный период времени. Теперь проблема в том, что - в зависимости от природы датчика, который отправляет данные, - в этот период времени может быть либо 50 наборов данных, либо 50 000. Поскольку я хочу визуализировать эти данные (используя ASP.NET / c #), для первого предварительного просмотра я бы хотел ВЫБРАТЬ из таблицы только 1000 значений.

У меня уже есть подход, заключающийся в следующем: я подсчитываю строки в интересующем периоде времени с простым предложением «где», чтобы указать идентификатор датчика, сохраняю его как переменную в SQL, а затем делю счетчик ( ) на 1000. Я пробовал в MS Access, где он работает просто отлично:

set @divider = select count(*) from table where [...]

SELECT (Int([RowNumber]/@divider)), First(Value)
FROM myTable
GROUP BY (Int([RowNumber]/@divider));

Хитрость в Access заключалась в том, что у меня просто есть поле данных ("RowNumber"), которое является моим PK / ID, и идет от 0 до. Я пытался добиться этого в SQL Server, используя метод ROW_NUMBER(), который работает более или менее. У меня правильный синтаксис для метода, но я не могу использовать оператор GROUP BY

Оконные функции могут появляться только в SELECT или ORDER BY статьи.

значение ROW_NUMBER() не может быть в выражении GROUP BY.

Теперь я застрял. Я пытался сохранить значение ROW_NUMBER в символ или отдельный столбец, а потом GROUP BY, но не смог этого сделать. И почему-то я начинаю думать, что моя стратегия может иметь свои слабые стороны ...? : /

Чтобы еще раз уточнить: мне не нужно SELECT TOP 1000 из моей таблицы, потому что это будет означать, что я выберу первые 1000 значений (в зависимости от сортировки). Мне нужно SELECT каждое x-е значение, пока я могу вычислить x (и я мог бы даже округлить его до INT, если это помогло бы сделать это). Надеюсь, я смог описать проблему понятно ...

Это мой первый пост в StackOverflow, надеюсь, я не забыл ничего важного или важного, если вам нужна дополнительная информация (структура таблицы, мои запросы ...), пожалуйста, не стесняйтесь спрашивать , Любая помощь или подсказка высоко ценится - заранее спасибо! :)


Обновление: РЕШЕНИЕ! Большое спасибо https://stackoverflow.com/users/52598/lieven!!!

Вот как я это сделал в итоге:

Я объявляю 2 переменные - я считаю свои строки и УСТАНАВЛИВАЮ их в первую переменную. Затем я использую ROUND () для только что назначенной переменной и делю ее на 1000 (потому что в конце я хочу около 1000 значений!). Я разделил эту операцию на 2 переменные, потому что, если я использовал значение из функции COUNT в качестве основы для моей операции ROUND, возникли некоторые ошибки.

declare @myvar decimal(10,2) 
declare @myvar2 decimal(10,2)

set @myvar = (select COUNT(*)
from value_table
where channelid=135 and myDate >= '2011-01-14 22:00:00.000' and myDate <= '2011-02-14 22:00:00.000'
)

set @ myvar2 = ROUND (@ myvar / 1000, 0)

Теперь у меня есть округленное значение, которое я хочу использовать в качестве размера шага (примите каждое x-ое значение -> это наш "x";)), хранящееся в @ myvar2. Затем я выберу данные нужного промежутка времени и канала и добавлю ROW_NUMBER () в качестве столбца «rn», и, наконец, добавлю предложение WHERE во внешний SELECT, где я делю ROW_NUMBER на @ myvar2 - когда модуль равен 0, строка будет выбрана.

select * from
(
select (ROW_NUMBER() over (order by id desc)) as rn, myValue, myDate
from value_table
where channel_id=135 and myDate >= '2011-01-14 22:00:00.000' and myDate<= '2011-02-14 22:00:00.000'
) d
WHERE rn % @myvar2 = 0

Работает как шарм - еще раз все мои благодарности https://stackoverflow.com/users/52598/lieven, см. Комментарий ниже для оригинального сообщения!

Ответы [ 2 ]

6 голосов
/ 20 марта 2012

В сущности, все, что вам нужно сделать, чтобы выбрать x-е значение, - это сохранить все строки, в которых модуль умноженного на число числа, деленного на x, равен 0.

WHERE rn % @x_thValues = 0

Теперь, чтобы иметь возможность использовать результат ROW_NUMBER, вам нужно обернуть весь оператор в подвыбор

SELECT  *
FROM    (
            SELECT  *
                    , rn = ROW_NUMBER() OVER (ORDER BY Value)
            FROM    DummyData
        ) d
WHERE   rn % @x_thValues = 0                    

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

DECLARE @x_thValues INTEGER = 2

;WITH DummyData AS (SELECT * FROM (VALUES (1), (2), (3), (4)) v (Value))
SELECT  *
FROM    (
            SELECT  *
                    , rn = ROW_NUMBER() OVER (ORDER BY Value)
            FROM    DummyData
        ) d
WHERE   rn % @x_thValues = 0                    
0 голосов
/ 20 марта 2012

Еще один вариант для рассмотрения:

Select Top 1000 * 
From dbo.SomeTable 
Where ....
Order By NewID()

, но, честно говоря, больше похоже на предыдущий ответ, чем этот.Вопрос может быть о производительности ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...