Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Помогите с выборкой
 
 автор: новичек   (10.07.2005 в 12:06)
 
 

есть выборка

<?
$qry_sbalance 
"select sum(exchange) from lines where
    uid=
$user_id and status='$STATUS_ENUM_ENABLE'
    and pmt_type<>'
$TRANS_ENUM_SPEND' and date<now()";
$sbalance db_get_id($qry_sbalance);
?>

так вот, задача состоит в том, чтобы выбирать количество записей равное какому-то числу, к примеру 10.

тоесть если есть записей меньше 10, то нечего не выбирается, если есть больше 10, к примеру 12, то выбирается 10, а 2 игнорируется, если есть к примеру 24, то выбирается 20, а 4 игнорируется.

надеюсь ясно обьянил что нужно.

подскажите пожалуйста.

   
 
 автор: cheops   (10.07.2005 в 12:43)   письмо автору
 
   для: новичек   (10.07.2005 в 12:06)
 

Для этого в конце запроса используется инструкция LIMIT - запрос вида
SLECT * FROM tbl LIMIT 10

выберет 10 записей
SLECT * FROM tbl LIMIT 20

выберет 20 записей
SLECT * FROM tbl LIMIT 10, 10

выберет 10 записей, начиная с 10
SLECT * FROM tbl LIMIT 20, 10

выберет 10 записей начиная с 20

В том конетексте, который требуется вам - потребуется сначала опеределить число записей, а затем динамически при помощи PHP формировать значения параметров для инструкции LIMIT.

   
 
 автор: новичек   (10.07.2005 в 13:03)
 
   для: cheops   (10.07.2005 в 12:43)
 

насчет LIMIT я знаю
а как опеределить число записей, а затем динамически при помощи PHP сформировать значения параметров для инструкции LIMIT ?

   
 
 автор: cheops   (10.07.2005 в 15:54)   письмо автору
 
   для: новичек   (10.07.2005 в 13:03)
 

Для этого необходимо выполнить запрос, который подсчитает число строк в вашем будующем запросе
<? 
$qry_sbalance 
"select count(*) from lines where 
    uid=
$user_id and status='$STATUS_ENUM_ENABLE
    and pmt_type<>'
$TRANS_ENUM_SPEND' and date<now()"
$sbalance db_get_id($qry_sbalance); 
if(!
$sbalance) exit(mysql_error());
$total mysql_result($sbalance,0);
?>

$total будет содержать число записей, в зависимости от полученного числа принимайте решение, если $total<10 вообще не запрашивайте данные, если больше 10, но меньше 20 значение в LIMIT выставьте в 10
<? 
if($total 10 && $total 20$num 10;
$qry_sbalance "select sum(exchange) from lines where 
    uid=
$user_id and status='$STATUS_ENUM_ENABLE
    and pmt_type<>'
$TRANS_ENUM_SPEND' and date<now() LIMIT $num"
$sbalance db_get_id($qry_sbalance); 
?>

Только логику округления до 10 нужно продумать...

   
 
 автор: новичек   (10.07.2005 в 21:31)
 
   для: cheops   (10.07.2005 в 15:54)
 

спасибо.
все это конечно хорошо если строк до 20, а если их будет больше ?
не очень хочется к примеру напихивать так

if($total > 20 && $total < 30) $num = 20;
//
if($total > 30 && $total < 40) $num = 30;

и т.д.

тоесть их может быть неограниченное количество, как можно сделать чтобы автоматом определяла кратность и правильность определения $num ?

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

   
 
 автор: новичек   (10.07.2005 в 23:08)
 
   для: новичек   (10.07.2005 в 21:31)
 

и еще такой момент
есть поле p_id, тоесть могут быть записи с одинаковыми данными

uid=$user_id and status='$STATUS_ENUM_ENABLE'
    and pmt_type<>'$TRANS_ENUM_SPEND' and date<now()

но с разными по p_id, тоесть получается что надо как то сгруппировать по p_id и все что проходит по условию ссумировать поле sum(exchange)

может все это так сложно сделать, может посоветуете какой другой вариант выборки ???

   
 
 автор: cheops   (11.07.2005 в 01:02)   письмо автору
 
   для: новичек   (10.07.2005 в 23:08)
 

А вы не могли бы привести пример того, что нужно получить, т.е. что на входе, а что должно быть на выходе?

   
 
 автор: cheops   (11.07.2005 в 01:00)   письмо автору
 
   для: новичек   (10.07.2005 в 21:31)
 

Ну эта задача решаемая, нужно разделить $total на 10, округлить результат в меньшую сторону при помощи функции floor() и опять умножить на 10.
<?php
  $num 
$total/10;
  
$num floor($num);
  
$num $num*10;
?>

   
 
 автор: новичек   (11.07.2005 в 01:54)
 
   для: cheops   (11.07.2005 в 01:00)
 

спасибо с этим ясно.
а насчет того что на входе и что должно быть на выходе.
суть такая, пользователь написал статью, ее порядковый номер заносится в p_id, каждый день создается таблица в которую заносится сколько оригинальных человек эту статью просмотрело, за каждого просмотревшего заносится премиальный бонус в поле exchange, к примеру за 10 дней суммируются все бонусы по этой статье и выводятся в графу в акке, он может эти бонусы потратить (на что не столь важно), если он их тратит, то упдатится графа pmt_type по этим дням и в дальнейшем эти дни не учитываются. но он может их не тратить а накапливать.
но вот к примеру он написал сегодня статью и завтра статью, и через 2 дня еще одну, через 11 дней, после написания первой статьи период начисления истекает по этим первым обеим статьям, значит должны подсчитатся бонусы по ним обеим, а по третьей статье период начисления (10 дней) еще не истек, значит она учитываться не должна.
статья может висеть 30, 60, 90,120 дней, потом она удаляется (в дальнейшем может срок будет увеличин), значит каждые 10 дней происходит обсчет бонусов.
если к примеру одна статья провисела 20, другая 33, и пользователь не тратил бонусу, то должна вывестись сумма за первую за 20 дней + сумма за вторую за 30 дней.
надеюсь саму суть подсчета обьяснил.
вот как это лучше реализовать ?

   
 
 автор: cheops   (11.07.2005 в 02:19)   письмо автору
 
   для: новичек   (11.07.2005 в 01:54)
 

Здесь удобно воспользоваться группировкой по полю p_id при помощи конструкции GROUP BY
select sum(exchange) from lines
where uid=$user_id and status='$STATUS_ENUM_ENABLE' and
   pmt_type<>'$TRANS_ENUM_SPEND'
GROUP BY p_id

   
 
 автор: новичек   (11.07.2005 в 02:35)
 
   для: cheops   (11.07.2005 в 02:19)
 

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

   
 
 автор: cheops   (11.07.2005 в 12:59)   письмо автору
 
   для: новичек   (11.07.2005 в 02:35)
 

Мне несколько трудно это сделать, так как я не совсем понимаю логику запроса, например строку "and date<now()", ведь дата казалось бы всегда будет меншье текущей?

   
 
 автор: новичек   (11.07.2005 в 13:05)
 
   для: cheops   (11.07.2005 в 12:59)
 

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

   
 
 автор: cheops   (11.07.2005 в 13:12)   письмо автору
 
   для: новичек   (11.07.2005 в 13:05)
 

У меня то нет структуры таблицы :))), а сам я предпочитаю использовать тип DATETIME и прибегаю к DATE только в специальных случаях...

   
 
 автор: новичек   (11.07.2005 в 13:25)
 
   для: cheops   (11.07.2005 в 13:12)
 

ну получается что это должно выглядить как то так ?

$qry_sbalance = "select count(*) from lines where 
    uid=$user_id and status='$STATUS_ENUM_ENABLE' 
    and pmt_type<>'$TRANS_ENUM_SPEND' and date<now()
    GROUP BY p_id "; 
$sbalance = db_get_id($qry_sbalance); 
if(!$sbalance) exit(mysql_error()); 
$total = mysql_result($sbalance,0); 
$num = $total/10; 
$num = floor($num); 
$num = $num*10;
$qry_sbalance = "select sum(exchange) from lines where 
    uid=$user_id and status='$STATUS_ENUM_ENABLE' 
    and pmt_type<>'$TRANS_ENUM_SPEND' and date<now() LIMIT $num"; 
$sbalance = db_get_id($qry_sbalance); 
?>

только я не пойму тогда, как будут суммироваться все суммы выбраных груп ?

   
 
 автор: cheops   (11.07.2005 в 13:35)   письмо автору
 
   для: новичек   (11.07.2005 в 13:25)
 

Нет, имеется ввиду
<?
$qry_sbalance 
"select count(*) from lines where 
    uid=
$user_id and status='$STATUS_ENUM_ENABLE
    and pmt_type<>'
$TRANS_ENUM_SPEND' and date<now() 
     "

$sbalance db_get_id($qry_sbalance); 
if(!
$sbalance) exit(mysql_error()); 
$total mysql_result($sbalance,0); 
$num $total/10
$num floor($num); 
$num $num*10
$qry_sbalance "select sum(exchange) from lines where 
    uid=
$user_id and status='$STATUS_ENUM_ENABLE
    and pmt_type<>'
$TRANS_ENUM_SPEND' and date<now() GROUP BY p_id LIMIT $num"
$sbalance db_get_id($qry_sbalance); 
?>

   
 
 автор: новичек   (11.07.2005 в 14:06)
 
   для: cheops   (11.07.2005 в 13:35)
 

ок
спасибо, щас попробую

   
 
 автор: новичек   (11.07.2005 в 22:48)
 
   для: новичек   (11.07.2005 в 14:06)
 

уважаемый ХЕОПС, вроде все работает, но есть один баг которого я не могу понять, запрос совершенно не реагирует на LIMIT, пробовал вместо переменной подставлять конкретное число, не помогает.
тоесть если есть к примеру в группе 12 записей, то она так и считает 12, а не 10 как должно быть, такое впечатление что LIMIT вообще не прописан.
в чем может быть дело ?

   
 
 автор: новичек   (11.07.2005 в 23:47)
 
   для: новичек   (11.07.2005 в 22:48)
 

и еще, как при таком запросе вытащить значение p_id , что бы знать какие группы она суммирует ?

   
 
 автор: cheops   (12.07.2005 в 00:48)   письмо автору
 
   для: новичек   (11.07.2005 в 23:47)
 

А прямо через запятую, MySQL здесь нарушает стандарт SQL и позволяет помещать рядом с агрегатными функциями имена столбцов, по которым происходит группировка
<?php
$qry_sbalance 
"select p_id, sum(exchange) from lines where 
    uid=
$user_id and status='$STATUS_ENUM_ENABLE
    and pmt_type<>'
$TRANS_ENUM_SPEND' and date<now() GROUP BY p_id LIMIT $num";
?>

   
 
 автор: новичек   (12.07.2005 в 00:56)
 
   для: cheops   (12.07.2005 в 00:48)
 

MySQL 4.1.8-max
я так прописал, но как мне вывести чтобы она была видимой переменной, тоесть к примеру

$pp_id = $что-то[p_id'];

что нужно подставить вместо что-то ?
или как то по другому она выводится ?

   
 
 автор: cheops   (12.07.2005 в 01:02)   письмо автору
 
   для: новичек   (12.07.2005 в 00:56)
 

Можно воспользоваться следующим кодом
<?php
  $sbalance 
mysql_query($qry_sbalance); 
  if(!
$sbalance) exit(mysql_error()); 
  while(
$total mysql_fetch_array($sbalance))
  {
    echo 
$total['p_id']."<br>";
  }
?>

   
 
 автор: новичек   (12.07.2005 в 01:12)
 
   для: cheops   (12.07.2005 в 01:02)
 

спасибо попробую, а насчет LIMITа никаких пожеланий не будет ?

   
 
 автор: cheops   (12.07.2005 в 00:49)   письмо автору
 
   для: новичек   (11.07.2005 в 22:48)
 

Хм... вообще-то не должно бы... а версия MySQL какая?

   
 
 автор: новичек   (12.07.2005 в 20:39)
 
   для: cheops   (12.07.2005 в 00:49)
 

и еще такая проблема
предположим, что в поле pmt_id 2 группы 9 и 10, в поле exchange у этих групп разные значения, у одной 0.1 у другой 0.15, общее число $num = 40 к примеру, из 40 10 это группы 9, а 30 это группы 10, по идеи она должна вывести общую сумму 2 групп 1+4.5=5.5, но она выводит сумму только одной группы. а если к примеру в 9 группе не 10 а 15 таблиц, а так как $num=40, то она и выводит общию сумму 1.5, а вторая група просто игнорируется.
как это все исправить, чтобы правильно работало ???
помогите, горю !!!

   
 
 автор: новичек   (12.07.2005 в 21:10)
 
   для: новичек   (12.07.2005 в 20:39)
 

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

   
 
 автор: cheops   (12.07.2005 в 21:57)   письмо автору
 
   для: новичек   (12.07.2005 в 21:10)
 

Вот без кратных 10 эта задача решается при помощи запроса
SELECT p_id, sum(exchange) 
FROM lines
GROUP BY p_id WITH ROLLUP;

WITH ROLLUP - выводит в конце сумму по группам (правда введён в MySQL, начиная только с 4.1.1).

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования