Выберите самую последнюю дату, но меньше, чем сегодняшняя дата в списке записей - PullRequest
3 голосов
/ 19 марта 2011
grade_id
grade_name
price
update_date.

Есть несколько записей для данного класса, с разной датой и ценой ...:

grade_id   grade_name  price  update_date (y-m-d)
1           A          8$      2011-02-01
1           A          10$     2011-03-01
1           A          20$     2011-04-01
2           B          10$     2011-02-01
2           B          20$     2011-03-01
2           B          30$     2011-04-01

Как я могу получить последнюю обновленную цену (но в прошлом) с выбранными запросами .. получить:

1           A          10$     2011-03-01
2           B          20$     2011-03-01

в результате ... (потому что самая последняя цена, с прошедшей датой ..

ТНХ Дэвид

Ответы [ 5 ]

4 голосов
/ 19 марта 2011
  SELECT t1.grade_id, t1.grade_name, t1.price, t1.update_date
    FROM my_tbl t1
         LEFT JOIN my_tbl t2 on t2.grade_id = t1.grade_id
     AND t2.update_date > t1.update_date
     AND t2.update_date < CURRENT_DATE
   WHERE t1.update_date < CURRENT_DATE
     AND t2.grade_id IS NULL
ORDER BY t1.grade_name
1 голос
/ 20 марта 2011

Не самое быстрое решение для большого числа записей, но удобочитаемое.

select *
  from table t1
 where update_date = 
        (select max(update_date)
           from table t2
          where t2.grade_id = t1.grade_id
            and t2.update_date < current_date);

Помогает первичный ключ (grade_id, update_date) в таблице InnoDB.

1 голос
/ 19 марта 2011
root@natasha:test> CREATE TABLE t (grade_id INT UNSIGNED NOT NULL, grade_name CHAR(1) NOT NULL, price CHAR(3) NOT NULL, update_date DATE);
Query OK, 0 rows affected (0.10 sec)

root@natasha:test> INSERT INTO t VALUES (1, 'A', '8$', '2011-02-01'), (1, 'A', '10$', '2011-03-01'), (1, 'A', '20$', '2011-04-01'), (2, 'B', '10$', '2011-02-01'), (2, 'B', '20$', '2011-03-01'), (2, 'B', '30$', '2011-04-01');
Query OK, 6 rows affected (0.13 sec)
Records: 6  Duplicates: 0  Warnings: 0

root@natasha:test> SELECT * FROM t;
+----------+------------+-------+-------------+
| grade_id | grade_name | price | update_date |
+----------+------------+-------+-------------+
|        1 | A          | 8$    | 2011-02-01  |
|        1 | A          | 10$   | 2011-03-01  |
|        1 | A          | 20$   | 2011-04-01  |
|        2 | B          | 10$   | 2011-02-01  |
|        2 | B          | 20$   | 2011-03-01  |
|        2 | B          | 30$   | 2011-04-01  |
+----------+------------+-------+-------------+
6 rows in set (0.00 sec)

root@natasha:test> SELECT * FROM (SELECT * FROM t WHERE update_date < DATE(NOW()) ORDER BY update_date DESC) AS `t` GROUP BY grade_id;
+----------+------------+-------+-------------+
| grade_id | grade_name | price | update_date |
+----------+------------+-------+-------------+
|        1 | A          | 10$   | 2011-03-01  |
|        2 | B          | 20$   | 2011-03-01  |
+----------+------------+-------+-------------+
2 rows in set (0.00 sec)
0 голосов
/ 19 марта 2011
select t1.* from table as t1
inner join (
select grade_id,max(update_date) as update_date
from table where update_date < curdate() group by grade_id ) as t2
on t1.grade_id = t2.grade_id and t1.update_date = t2.update_date

Добавить индекс в таблицу (grade_id, update_date)

0 голосов
/ 19 марта 2011
SELECT MAX(update_date) FROM table WHERE DATE(update_date) != DATE(NOW());
...