Большой Воронежский Форум
Страница 1 из 2
1 2 >
» Веб-дизайн>Проблема с запросом SQL
V_L 10:07 11.08.2006
просьба, подскажите как.

|name| data |count|
| n1 |2006-10-10| 5 |
| n2 |2006-10-11| 4 |
| n1 |2006-10-12| 3 |
| n1 |2006-10-13| 4 |
| n2 |2006-10-13| 6 |
| n1 |2006-10-14| 4 |
| n3 |2006-10-15| 8 |
| n1 |2006-10-16| 4 |
| n3 |2006-10-17| 9 |
| n1 |2006-10-18| 4 |

есть такая таблица
нужен sql запрос, который бы удалял записи, кроме
уникальных по столбцу name при последней дате, т.е.

таблица после запроса была бы такой:

|name| data |count|
| n2 |2006-10-13| 6 |
| n3 |2006-10-17| 9 |
| n1 |2006-10-18| 4 | [Ответ]
B. 10:10 11.08.2006
Сервер какой? [mysql/postgress/...] и версия? [Ответ]
V_L 10:14 11.08.2006
сервер MySQL 4 [Ответ]
maximn 10:18 11.08.2006

Сообщение от V_L:
сервер MySQL 4

одним запросом никак, на 5 можно было бы вложенными

двумя - первым ищете строки, вторым удаляете их

пысы. и введите нормальный ключ, раз уж вам нужны операции удаления на таблице [Ответ]
V_L 10:21 11.08.2006
ключ есть просто я его не указал
тип int, auto_increment
пыталсявот таким но там ошибка
DELETE * FROM `tabl` WHERE NOT(`name`=(SELECT DISTINCT `name` FROM `tabl`)) [Ответ]
alemiks 14:16 11.08.2006

Сообщение от maximn:
одним запросом никак, на 5 можно было бы вложенными

это как ? выполнять select на той же таблице, из которой удаляются записи ? приведите плз работающий запрос [Ответ]
maximn 14:32 11.08.2006

Сообщение от alemiks:
выполнять select на той же таблице, из которой удаляются записи

именно

Сообщение от alemiks:
приведите плз работающий запрос

ну что то наподобие "delete from tbl where id in (select ...)" - уверен, у вас прекрасно получится заставить его работать самостоятельно. [Ответ]
alemiks 14:35 11.08.2006

Сообщение от maximn:
ну что то наподобие "delete from tbl where id in (select ...)" - уверен, у вас прекрасно получится заставить его работать самостоятельно.

ну что Вы, у меня кроме "You can't specify target table 'xxx' for update in FROM clause" не получается. вся надежда на Вас ))) [Ответ]
maximn 15:11 11.08.2006

Сообщение от alemiks:
ну что Вы, у меня кроме "You can't specify target table 'xxx' for update in FROM clause" не получается. вся надежда на Вас )))

к сожалению, я тоже не волшебник

хотя способ сделать все одним запросом безусловно есть
[Ответ]
maximn 15:23 11.08.2006
не совсем про это, но вот хороший раздел из фака - кстати в нем есть оптимальный способ удаления (через временную таблицу):

3.6.4. The Rows Holding the Group-wise Maximum of a Certain Field
“For each article, find the dealer or dealers with the most expensive price.”

In standard SQL (and as of MySQL 4.1), the problem can be solved with a subquery like this:

SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);

In MySQL versions prior to 4.1, it's best do it in several steps:

Get the list of (article,maxprice) pairs.

For each article, get the corresponding rows that have the stored maximum price.

This can easily be done with a temporary table and a join:

CREATE TEMPORARY TABLE tmp (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL);

LOCK TABLES shop READ;

INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;

SELECT shop.article, dealer, shop.price FROM shop, tmp
WHERE shop.article=tmp.article AND shop.price=tmp.price;

UNLOCK TABLES;

DROP TABLE tmp;

If you don't use a TEMPORARY table, you must also lock the tmp table.

“Can it be done with a single query?”

Yes, but only by using a quite inefficient trick called the “MAX-CONCAT trick”:

SELECT article,
SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,
0.00+LEFT( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price
FROM shop
GROUP BY article;

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | C | 1.69 |
| 0004 | D | 19.95 |
+---------+--------+-------+

The last example can be made a bit more efficient by doing the splitting of the concatenated column in the client. [Ответ]
Vital_N 15:32 11.08.2006
ИМХО намного проще и быстрее все это сделать двумя запросами (обращениями к бд) и не париться [Ответ]
V_L 15:41 11.08.2006
если вас не затруднит, то какими?

пробовал этим:
delete
FROM `tabl`
WHERE `name` <> any(

SELECT DISTINCT 'name'
FROM `tabl`
)
тоже нет,
замучился,а надо чтоб одним запросом [Ответ]
Vital_N 15:46 11.08.2006
V_L, почему такая необходимость сделать одним запросом? [Ответ]
V_L 15:49 11.08.2006
Vital_N очень надо
не я это решаю.

проблему можно решить если бы
SELECT DISTINCT 'name' FROM `tabl`
возвращал не только name, но и id, ноя не знаю как это сделать [Ответ]
maximn 15:50 11.08.2006

Сообщение от V_L:
проблему можно решить если бы
SELECT DISTINCT 'ip' FROM `statistika`
возвращал не только name, но и id, ноя не знаю как это сделать

я не понял, вам удалять или выбрать? [Ответ]
Vital_N 15:53 11.08.2006
а причем тут DISTINCT 'name' ? тебе ж последняя дата нужна? и не список уникальных имен? [Ответ]
V_L 15:54 11.08.2006
ну это подзапрос,который мне бы позволил потом удалить что я хочу [Ответ]
Vital_N 15:55 11.08.2006
у тебя с увлечением ид - дата увеличивается? т.е записи с макс ИД - являются записями с наиболее бОльшей датой? [Ответ]
V_L 15:56 11.08.2006
да так [Ответ]
Vital_N 15:58 11.08.2006
---поскипано
гоню - так нельзя [Ответ]
Vital_N 16:02 11.08.2006
думаю одним запросом этого технически невозможно сделать - либо как Макс сказал - через временные таблицы - либо двумя запросами и программными средствами [Ответ]
maximn 16:04 11.08.2006
тоже склоняюсь к варианту что скорее всего одним нельзя - будь это селект а не делит, все было бы совсем по-другому [Ответ]
maximn 16:08 11.08.2006
либо переделать механизм добавления строк - ввести поле по которому можно было бы потом сносить [Ответ]
Vital_N 16:11 11.08.2006
угу - типа флажок - что сия запись есть последняя - остальные хлам )) либо вообще хранить только последние записи )) [Ответ]
Vital_N 16:13 11.08.2006
V_L, тебе это ради эксперимента надо - или есть практическая задача? может быть ее можно по другому решить? [Ответ]
alemiks 17:16 11.08.2006

Сообщение от V_L:
очень надо
не я это решаю.

наверное попался заказчик, которому в админке нужна одна большая кнопка с надписью «зделать фсе как нада» )))
причем заказчик еще и разбирается в SQL 8-O
ужасное стечение обстоятельств [Ответ]
B. 00:12 12.08.2006
М.б. так:
SELECT id, DISTINCT name FROM table ORDER BY date;
DELETE FROM TABLE WHERE <id не вошло в предыдущий select>

Однако не уверен, что SELECT вернет именно то, что надо. [Ответ]
alemiks 00:23 12.08.2006

Сообщение от B.:
М.б. так:
SELECT id, DISTINCT name FROM table ORDER BY date;
DELETE FROM TABLE WHERE <id не вошло в предыдущий select>
Однако не уверен, что SELECT вернет именно то, что надо.

и как delete узнает, что не вошло в select ? =) как все просто в теории)

предлагаю работающий вариант (сидел специально ковырялся)
1. выкинуть mysql4
2. поставить mysql5
3. написать хранимую процедуру

Сообщение от :
CREATE PROCEDURE `clear_all_but_last`()
BEGIN
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_test(
`name` VARCHAR(20) DEFAULT NULL,
`data` INT(11) DEFAULT NULL,
`count` INT(11) DEFAULT NULL
) ENGINE=MyISAM;
INSERT INTO tmp_test SELECT t1.* FROM test AS t1 WHERE t1.data NOT IN
(SELECT MAX(t2.data) FROM test AS t2 WHERE t2.name=t1.name);
DELETE FROM test WHERE test.data IN (SELECT tmp_test.data FROM tmp_test);
END;

4. удаление будет в одну строку, как и требовалось)

Сообщение от :
CALL clear_all_but_last();

p.s. дату лучше хранить как timestamp, хотя функция MAX и со строками будет работать [Ответ]
V_L 09:30 15.08.2006
alemiks спасибо, но к сожелению 5 mysql никак нельзя,
вариант с добавочным полем конечно решает, но база уже сущ и довольно большая [Ответ]
nistelroi 21:30 11.08.2014
Для автора топика тема конечно не актуальна, но кто наткнулся в поиске как я возможно пригодится.
Есть два способа обойти ошибку. Например вот простейшее решение, одним запросом

Сообщение от :
DELETE t1
FROM таблица t1
JOIN таблица t2 ON t2.name = t1.name AND t2.data > t1.data

[Ответ]
Страница 1 из 2
1 2 >
Вверх