1

Всем доброго, позитивного дня

 SELECT
     `table1`.`field1`, `table1`.`field2`, etc..
 FROM                                                               
     `table1` as `t1`
 INNER JOIN 
     `table2` as `t1` ON `t1`.`field1`=`t2`.`field2`           
 WHERE 1
     AND `t1`.`field1`>'0'
     AND `t1.`field2`>'0'
     AND `t2`.`field1`='1'
     ..etc
 GROUP BY `t1`.`field1`
 ORDER BY `t1`.`field2` DESC, `t1`.`field3` ASC
 LIMIT 0,10

Есть запрос к БД. Там есть GROUP BY, что сильно портит картину. Охота посчитать кол-во записей с данным условием. И тут начинаются приключения

// 1
// вместо полей таблиц написать - count(*)
// получаю много записей, которые надо все суммировать

// 2
// убрать GROUP BY
// получаю записей больше чем есть, что собственно логично

// 3
// делать такой же запрос только по `table1`.`field1` без LIMIT
// ресурсо-расточительно

// 4
// дописать Count(*) после перечисления полей
// аналогично пункту 2

Подскажите, как получить счетчик записей. Можно ли в 1 запрос запихать такое?

Akina
  • 31,807
gforce
  • 426
  • 6
  • 13
  • SELECT SQL_CALC_FOUND_ROWS <остальной текст запроса>;, после чего СРАЗУ SELECT FOUND_ROWS();. – Akina Apr 06 '18 at 06:07
  • Вау! Спасибо, самое то. Ну хоть в ответ напишите, а не в коммент – gforce Apr 06 '18 at 06:20

1 Answers1

4

Если нужно посчитать количество записей в запросе после группировки, то в запрос следует добавить SQL_CALC_FOUND_ROWS, который выполнит такой подсчёт:

SELECT SQL_CALC_FOUND_ROWS <остальной текст запроса>;

и сразу после запроса выполнить запрос на получение количества записей:

SELECT FOUND_ROWS();

Если mysqli поддерживает мультизапросы (два и более запросов в одном операторе) - можно оба запроса выполнить одним оператором, тогда он вернёт два набора записей, в первом будут записи запроса, во втором одна запись с их количеством.

===========================

Если же речь идёт о том, что нужно посчитать количество записей ДО группировки, следует добавить к выражению группировки модификатор WITH ROLLUP, а в список полей выходного набора выражение COUNT(*). При этом в результирующий набор записей добавится ещё одна запись, где поле группировки будет иметь значение NULL, а в поле COUNT(*) будет суммарное количество записей до группировки.

Если в выражение группировки входит несколько полей, будет добавлено несколько записей - для каждого уровня группировки. Чтобы оставить только суммарное, нужно будет выполнить дополнительный отбор в секции HAVING:

GROUP BY <grouping fieldset> WITH ROLLUP
HAVING <last field in group by> IS NOT NULL -- записи основного запроса
    OR <first field in group by> IS NULL -- запись с количеством

Важно! применение модификатора WITH ROLLUP предполагает, что последнее (тем более несколько последних) поле группировки не содержит значения Null. В противном случае в выходном наборе будут пары идентичных, кроме поля COUNT(*), записей - одна из результирующего набора, вторая - с подсчётом количества записей в группе. Если же последнее поле группировки всё же содержит Null, выходом является добавление в источник записей псевдотаблицы с единственной not-Null записью, и добавление этого поля в выражение группировки, причём последним.

SELECT <выходной набор>, dummyfield.dummytable
FROM <источник данных - список таблиц и условий связи>
   , (select 1 as dummyfield) as dummytable
WHERE <условия отбора>
GROUP BY <выражения группировки>, dummyfield.dummytable
    WITH ROLLUP
HAVING dummyfield.dummytable IS NOT NULL
    OR <первое поле в выражении группировки> IS NULL
ORDER BY <выражения сортировки>

Именно по значению этого поля и определяем, суммарная это запись или частная, и по нему, если надо, выполняем фильтрацию.

Akina
  • 31,807