Требуется подсчет строк после оператора SELECT: каков оптимальный подход SQL?
Я пытаюсь выбрать столбец из одной таблицы 9X_sql-syntax (без объединений), и мне нужно подсчитать 9X_sql-syntax количество строк, в идеале, прежде чем я 9X_odbc начну извлекать строки. Я пришел к двум 9X_sqlncli подходам, которые предоставляют мне необходимую 9X_sqlselect информацию.
Подход 1:
SELECT COUNT( my_table.my_col ) AS row_count FROM my_table WHERE my_table.foo = 'bar'
Тогда
SELECT my_table.my_col FROM my_table WHERE my_table.foo = 'bar'
Или подход 2
SELECT my_table.my_col, ( SELECT COUNT ( my_table.my_col ) FROM my_table WHERE my_table.foo = 'bar' ) AS row_count FROM my_table WHERE my_table.foo = 'bar'
Я делаю это, потому 9X_sqlncli что мой драйвер SQL (SQL Native Client 9.0) не 9X_sql позволяет мне использовать SQLRowCount в 9X_sql-statement операторе SELECT, но мне нужно знать количество 9X_select-statement строк в моем результате, чтобы выделить 9X_sql-syntax массив перед присвоением информации Это. К 9X_sqlncli сожалению, использование динамически выделяемого 9X_sqlncli контейнера не является вариантом в этой 9X_sqlncli области моей программы.
Я обеспокоен тем, что 9X_sql-syntax может произойти следующий сценарий:
- ВЫБРАТЬ для подсчета.
- Выполняется другая инструкция: добавление или удаление строки.
- Выполняется SELECT для данных, и внезапно массив имеет неправильный размер.
-В худшем случае это попытается записать данные за пределами массива и выйдет из строя моя программа.
Запрещает 9X_sql ли подход 2 эту проблему?
Кроме того, будет 9X_sql-select ли один из двух подходов быстрее? Если да, то 9X_sql-syntax какие?
Наконец, есть ли лучший подход, который 9X_sql-statement я должен рассмотреть (возможно, способ указать 9X_sql драйверу, чтобы он возвращал количество 9X_sql-syntax строк в результате SELECT с помощью SQLRowCount?)
Для 9X_odbc тех, кто спрашивал, я использую Native C++ с 9X_sql-select вышеупомянутым драйвером SQL (предоставленным 9X_sqlselect Microsoft).
Ответ #1
Ответ на вопрос: Требуется подсчет строк после оператора SELECT: каков оптимальный подход SQL?
Если вы используете SQL Server, после запроса 9X_sql-statement вы можете выбрать функцию @@RowCount (или, если ваш 9X_sql-statement набор результатов может содержать более 9X_sql-query 2 миллиардов строк, используйте функцию 9X_sql-select RowCount_Big()). Это вернет количество строк, выбранных 9X_sql-syntax предыдущим оператором, или количество строк, затронутых 9X_sql-syntax оператором вставки / обновления / удаления.
SELECT my_table.my_col FROM my_table WHERE my_table.foo = 'bar' SELECT @@Rowcount
Или, если 9X_sqlselect вы хотите подсчитать количество строк, включенных 9X_sql-statement в результат, отправленный аналогично подходу 9X_sqlselect № 2, вы можете использовать тег OVER clause.
SELECT my_table.my_col, count(*) OVER(PARTITION BY my_table.foo) AS 'Count' FROM my_table WHERE my_table.foo = 'bar'
Использование 9X_sql-select предложения OVER будет иметь гораздо лучшую 9X_sql производительность, чем использование подзапроса 9X_select-statement для получения количества строк. Использование 9X_sql-select @@ RowCount будет иметь лучшую производительность, потому 9X_sql-query что не будет никакой стоимости запроса для 9X_sql-select оператора select @@ RowCount
Обновление в 9X_select-statement ответ на комментарий: В приведенном мной 9X_sql примере будет указано количество строк в 9X_sql-query разделе, определяемое в данном случае как 9X_odbc «PARTITION BY my_table.foo». Значение столбца 9X_sqlselect в каждой строке - это количество строк с 9X_sql-syntax одинаковым значением my_table.foo. Поскольку 9X_sql-syntax в вашем примере запроса было предложение 9X_sqlncli «WHERE my_table.foo = 'bar'», все строки 9X_sql-statement в наборе результатов будут иметь одинаковое 9X_sqlncli значение my_table.foo, и поэтому значение 9X_sql в столбце будет одинаковым для всех строк 9X_sqlselect и равным (в в данном случае) это # строк 9X_sql-query в запросе.
Вот лучший / более простой пример 9X_sqlselect того, как включить столбец в каждую строку, которая 9X_sql-query представляет собой общее количество строк 9X_sql-query в наборе результатов. Просто удалите необязательное 9X_sql-statement предложение Partition By.
SELECT my_table.my_col, count(*) OVER() AS 'Count' FROM my_table WHERE my_table.foo = 'bar'
Ответ #2
Ответ на вопрос: Требуется подсчет строк после оператора SELECT: каков оптимальный подход SQL?
Есть только два способа быть на 100% уверенными 9X_odbc в том, что COUNT(*)
и фактический запрос дадут согласованные 9X_sql-statement результаты:
- Объединение
COUNT(*)
с запросом, как в вашем Подходе 2. Я рекомендую форму, которую вы показываете в своем примере, а не форму коррелированного подзапроса, показанную в комментарии от kogus. - Используйте два запроса, как в вашем Подходе 1, после запуска транзакции на уровне изоляции
SNAPSHOT
илиSERIALIZABLE
.
Использование одного из этих 9X_select-statement уровней изоляции важно, поскольку любой 9X_sqlncli другой уровень изоляции позволяет новым 9X_sql-statement строкам, созданным другими клиентами, стать 9X_sql-statement видимыми в вашей текущей транзакции. Подробнее 9X_sql-statement читайте в документации MSDN на SET TRANSACTION ISOLATION
.
Ответ #3
Ответ на вопрос: Требуется подсчет строк после оператора SELECT: каков оптимальный подход SQL?
Подход 2 всегда возвращает счетчик, соответствующий 9X_sql-syntax вашему набору результатов.
Я предлагаю вам 9X_sql-statement связать подзапрос со своим внешним запросом, чтобы 9X_sql гарантировать, что условие в вашем счетчике 9X_sql соответствует условию в наборе данных.
SELECT mt.my_row, (SELECT COUNT(mt2.my_row) FROM my_table mt2 WHERE mt2.foo = mt.foo) as cnt FROM my_table mt WHERE mt.foo = 'bar';
Ответ #4
Ответ на вопрос: Требуется подсчет строк после оператора SELECT: каков оптимальный подход SQL?
Если вас беспокоит, что количество строк, соответствующих 9X_sql-select условию, может измениться за несколько миллисекунд 9X_sql-syntax с момента выполнения запроса и получения 9X_sql-statement результатов, вы можете / должны выполнять 9X_sql-select запросы внутри транзакции:
BEGIN TRAN bogus SELECT COUNT( my_table.my_col ) AS row_count FROM my_table WHERE my_table.foo = 'bar' SELECT my_table.my_col FROM my_table WHERE my_table.foo = 'bar' ROLLBACK TRAN bogus
Это всегда возвращает 9X_sqlselect правильные значения.
Кроме того, если вы 9X_sql-syntax используете SQL Server, вы можете использовать 9X_sql-query @@ ROWCOUNT, чтобы получить количество строк, затронутых 9X_sql-statement последним оператором, и перенаправить вывод 9X_sql реального запроса во временную таблицу или таблицу. переменная, поэтому 9X_sqlncli вы можете вернуть все сразу и без транзакции:
DECLARE @dummy INT SELECT my_table.my_col INTO #temp_table FROM my_table WHERE my_table.foo = 'bar' SET @dummy=@@ROWCOUNT SELECT @dummy, * FROM #temp_table
Ответ #5
Ответ на вопрос: Требуется подсчет строк после оператора SELECT: каков оптимальный подход SQL?
Вот несколько идей:
- Воспользуйтесь подходом №1 и измените размер массива для хранения дополнительных результатов или используйте тип, который автоматически изменяет размер по мере необходимости (вы не указываете, какой язык вы используете, поэтому я не могу быть более конкретным).
- Вы можете выполнить оба оператора в Подходе №1 внутри транзакции, чтобы гарантировать, что счетчики оба раза будут одинаковыми, если ваша база данных поддерживает это.
- Я не уверен, что вы делаете с данными, но если есть возможность обработать результаты, не сохраняя сначала их все, это может быть лучшим методом.
9X_sql
Ответ #6
Ответ на вопрос: Требуется подсчет строк после оператора SELECT: каков оптимальный подход SQL?
Если вы действительно обеспокоены тем, что 9X_sql-query количество ваших строк изменится между счетчиком 9X_sqlncli выбора и оператором выбора, почему бы сначала 9X_odbc не выбрать свои строки во временную таблицу? Таким 9X_sqlncli образом, вы будете синхронизированы.
-
4
-
8
-
3
-
3
-
6
-
5
-
9
-
9
-
4
-
5
-
3
-
4
-
4
-
3
-
2
-
7
-
6
-
3
-
2
-
3
-
6
-
2
-
4
-
2
-
1
-
8
-
2
-
2
-
4
-
2
-
1
-
1
-
4
-
3
-
1
-
2
-
3
-
3
-
9
-
3
-
5
-
3
-
3
-
2
-
3
-
3
-
5
-
7
-
1
-
1