MySQL query - ВЫБРАТЬ только самый последний результат определенной строки? - PullRequest
2 голосов
/ 12 января 2012

У меня есть этот запрос, который собирается автоматически создавать счет через cronjob, если дата истекшего купона ровно 1 месяц назад ИЛИ последняя дата выставления счета (b.date) ровно месяц назад. Условия могут произойти только один раз, потому что конкретная дата никогда не будет 1 месяц назад в будущем.

SELECT *

FROM `coupons` AS c 
LEFT JOIN `partners` AS p ON p.`id` = c.`pid`
LEFT JOIN `bills` AS b ON b.`pid` = c.`pid`   

WHERE 
(
CURRENT_DATE() = DATE_ADD(c.`expires`, INTERVAL 1 MONTH) // add something here?
OR
CURRENT_DATE() = DATE_ADD(b.`date`, INTERVAL 1 MONTH) 
)

Моя проблема в том, что в первом условии WHERE я получил более 1 результата. Поэтому я ищу решение для выбора только самой последней и только одной строки b.date.

Буду признателен за любую помощь.

Ответы [ 4 ]

1 голос
/ 12 января 2012

Проблема здесь в том, что bills относится к partners, а не к coupons. Ваш SQL, например, выглядит так:

  drop table if exists coupons;
  create table coupons (id int not null, pid int not null, expires date, primary key(id));
  drop table if exists bills;
  create table bills (id int not null, pid int not null, `date` date, primary key(id));
  drop table if exists partners;
  create table partners ( id int, name varchar(20), primary key(id));

Мы заполняем некоторые данные:

  insert into partners values (1,'One');
  insert into coupons values (1,1,'2011-12-12'), (2,1,'2011-11-11');
  insert into bills values (1,1,'2011-12-12'), (2,1,'2011-11-11');

На данный момент

  select * from coupons c
  left join partners p on c.pid = p.id
  left join bills b on b.pid = c.pid

возвращает 4 строки, что имеет смысл: (partner1, coupon1, bill1), (p1, c1, b2), (p1, c2, b1), (p1, c2, b2). Если мы добавим:

  where
  (
  current_date() = date_add(c.expires, interval 1 month)
  or
  current_date() = date_add(b.`date`, interval 1 month)
  )

Мы получаем 3 строки: (p1, c1, b1), (p1, c1, b2), (p1, c2, b1). Зачем? Потому что ни один из coupon2 или bill2 не проходит тест, в то время как по крайней мере одна из каждой другой комбинации делает это.

Я подозреваю, что то, что вы действительно ищете, ближе к:

  select *
  from coupons c
  where
  c.id in
  (select distinct c2.id from coupons c2 
    left join partners p2 on c2.pid=p2.id
    left join bills b2 on b2.pid=c2.pid
    where
     current_date()=date_add(c2.expires, interval 1 month)
     or
     current_date()=date_add(b2.`date`, interval 1 month)
  )

Здесь я использую подзапрос, чтобы получить список различных идентификаторов купонов для купонов, соответствующих вашему требованию, а затем просто получить эти купоны.

Но, играя с ним, я не уверен, что ваше требование точно имеет смысл: вы получаете купоны, у которых либо есть срок действия ровно месяц назад, либо которые связаны с партнером, который выставлен счет ровно месяц назад ? При таком подходе вы получаете только список купонов, а затем вам нужно будет получить последний счет или сведения о партнере, при условии, что всегда есть ассоциированный партнер? Есть ли?

Надеюсь, это поможет, Крейг

1 голос
/ 12 января 2012

Да, просто добавьте «LIMIT 1» в конце: см. Документацию MySQL для выбора .

Но учтите, что вам нужно будет добавить ORDER BY, чтобы убедиться, что выполучить «последний» ряд, в зависимости от того, что вы подразумеваете под этим - bills.date или coupons.expires?

1 голос
/ 12 января 2012

Используйте функцию Max в строке bills.date, если хотите использовать самый последний результат (см .: http://www.w3schools.com/sql/sql_func_max.asp).

0 голосов
/ 12 января 2012

Не уверен, работает ли он на MySQL, но как насчет LIMIT 1

...