|
|
|
| В таблице имеется поле cena для указания цены, поле artikul_kod для указания артикула, и поле metka, в котором присутствует одна их трех меток - "1С", "Ст" или "Дт". При этом с одним артикулом может только одна строка, а может быть две или три строки, отличающиеся полем metka.
Требуется отобрать товары по одному с каждым артикулом, отсортировав их по цене.
При этом, если с данным артикулом имеются три записи, то отбирается запись с меткой «1С».
Если с данным артикулом имеются две записи, одна из которых имеет метку «1С», то отбирается запись с меткой «1С».
Если имеются две записи, в одной из которых метка «Ст», а в другой метка «Дт», то отбирается запись с меткой «Ст».
Если с данным артикулом имеется только одна запись, то она и отбирается независимо от метки.
Можно ли построить такой запрос на базе SELECT или придется перебирать таблицу и удалять конкурентов для товаров с одинаковым артикулом? | |
|
|
|
|
|
|
|
для: Владимир55
(01.06.2013 в 23:52)
| | Вы это хотите одним запросом сделать? Или можно осуществить выборку несколькими запросами, как вариант объединив их UNION (впрочем последний вариант не очень хорош, так как сортировка таких таблиц осуществляется в файле на диске). | |
|
|
|
|
|
|
|
для: cheops
(02.06.2013 в 19:02)
| | Понятно, спасибо! | |
|
|
|
|
|
|
|
для: Владимир55
(01.06.2013 в 23:52)
| | Надеюсь тут не TEMPORARY table ?
Как Вам такое решение?
SELECT a.*
, case when c=1
or ( has_1c and metka='1С' )
or ( c=2 and has_1c-1 and metka='Ст' ) then 1 end use_this
FROM artikul_test a
JOIN( SELECT artikul
, count(*)c
, min(metka)='1С' has_1c
FROM artikul_test
GROUP BY artikul
)t USING( artikul )
HAVING use_this
| Пока вы посмотрите, я уже 6ой раз допиливаю и укорачиваю код =) | |
|
|
|
|
|
|
|
для: Sfinks
(03.06.2013 в 11:11)
| | Спасибо! | |
|
|
|
|
|
|
|
для: Sfinks
(03.06.2013 в 11:11)
| | А еще правильнее будет так:
/*<?*/
SELECT a.*
FROM artikul_test a
JOIN( SELECT artikul
, count(*)c
, min(metka)='1С' has_1c
FROM artikul_test
GROUP BY artikul
)t USING( artikul )
WHERE c=1
OR ( has_1c and metka='1С' )
OR ( c=2 and has_1c-1 and metka='Ст' )
|
| |
|
|
|
|
|
|
|
для: Sfinks
(06.06.2013 в 16:41)
| | Спасибо! | |
|
|
|
|
|
|
|
для: Sfinks
(06.06.2013 в 16:41)
| | И еще.
Если выполнить на эту таблицу
ALTER TABLE artikul_test ADD UNIQUE ( artikul, metka )
| , то EXPLAIN очень значительно улучшается.
Исчезает Using join buffer, Using temporary и Using filesort, тип выборки меняется сразу в двух подзапросах на более скоростные, и общее количество строк резко сокращается.
Кстати, тип поля metka у Вас ENUM? | |
|
|
|
|
|
|
|
для: Sfinks
(06.06.2013 в 19:24)
| | Для поля metka установлен тип CHAR. А про поле ENUM я даже не слышал, и в Справочнике у Симдянова его не обнаружил. Сюда оно очень подходит, спасибо!
Как я понял, это поле можно добавить к таблице, если изначально его нет
ALTER TABLE artikul_test ADD COLUMN metka ENUM('1С', 'Ст', 'Дт').
|
А как создать его непосредственно при создании таблицы? | |
|
|
|
|
|
|
|
для: Владимир55
(07.06.2013 в 10:28)
| |
CREATE TABLE `artikul_test` (`cena` int( 11 ) NOT NULL ,
`artikul` int( 11 ) NOT NULL ,
`metka` enum( '1С', 'Ст', 'Дт' ) NOT NULL
) ENGINE = MYISAM DEFAULT CHARSET = utf8;
| Как-то так.
> Сюда оно очень подходит, спасибо!
Оно ОЧЕНЬ подходит всегда, когда имеется список с ограниченным числом значений.
Не забывайте о нем.
Оно такое же быстрое, как и целочисленное, т.к. сервер с ним и работает как с именованными целыми числами.
Можете убедиться в этом, выполнив:
SELECT *, cast(metka AS unsigned)metka_numeric FROM artikul_test
| и
SELECT * FROM artikul_test WHERE metka=1
|
| |
|
|
|