Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > Ошибка при использовании DISTINCT, ORDER BY и CASE


Автор: polin11 20.6.2018, 14:01
  Есть запрос, он выполняется без ошибок, но есть дублирующие записи
Код

SELECT  "Field2"  FROM "Table1" WHERE "Fileld1" LIKE 'val%'
ORDER BY  CASE WHEN "Field2" = "Field3" THEN 1 ELSE 0 END



При попытке использовать DISTINCT, а именно
Код

SELECT  DISTINCT "Field2"  FROM "Table1" WHERE "Fileld1" LIKE 'val%'
ORDER BY  CASE WHEN "Field2" = "Field3" THEN 1 ELSE 0 END



возникает проблема: в конструкции SELECT DISTINCT выражения ORDER BY должны быть в списке выборки
не могу сообразить, как избавиться от дублей "Field2"

Автор: Snowy 20.6.2018, 14:47
По данной логике - никак.
Допустим имеем записи:

AAA BBB
AAA AAA
BBB AAA

Как в таком случае сортировать AAA, если он подпадает и туда и туда?
Тут нужно корректнее определиться, как сортировать.
Например, если хоть одна из AAA равна своему "Field3"
Код

SELECT "Field2" FROM "Table1" WHERE "Fileld1" LIKE 'val%'
GROUP BY "Field2"
ORDER BY "Field2" IN (SELECT "Field2" FROM "Table1" WHERE "Field2" = "Field3")


или, оставлять оба варианта, если если есть и такой и такой вариант:
Код

SELECT "Field2" FROM "Table1" t1 WHERE "Fileld1" LIKE 'val%' AND "Field2" <> "Field3" GROUP BY "Field2"
UNION ALL
SELECT "Field2" FROM "Table1" t1 WHERE "Fileld1" LIKE 'val%' AND "Field2" = "Field3" GROUP BY "Field2"

Автор: polin11 21.6.2018, 17:51
Работает такой вариант 
Код

 SELECT "Field2" FROM 
 (SELECT DISTINCT "Field2",  CASE WHEN "Field2" = "Field3" THEN 1 ELSE 0  END as Ord  
 FROM "Table1" WHERE "Field1" LIKE 'val%'
 ORDER BY Ord DESC ) T 



У меня еще один вопрос, есть аналогичный запрос с LIMIT
Код

 SELECT "Field2" FROM 
 (SELECT DISTINCT "Field2",  CASE WHEN "Field2" = "Field3" THEN 1 ELSE 0  END as Ord  
 FROM "Table1" WHERE "Field1" LIKE 'val%'
 ORDER BY Ord DESC LIMIT 20 ) T 



поправьте меня, если я не прав, при выполнении запроса планировщик пробежит ВСЕ записи, выполнит поиск по условию "Field1" LIKE 'val%', затем отсортирует по Ord и выдаст первые 20 записей, то есть по времени и ресурсам будет аналогично, этому же запросу, но без LIMIT 20

Автор: Snowy 21.6.2018, 19:08
Цитата(polin11 @  21.6.2018,  18:51 Найти цитируемый пост)
Работает такой вариант 

Не работает. Если одновременно будут записи с "Field2" = "Field3" и "Field2" <> "Field3", то запись будет в двух экземплярах, как в моём втором варианте.

Цитата(polin11 @  21.6.2018,  18:51 Найти цитируемый пост)
CASE WHEN "Field2" = "Field3" THEN 1 ELSE 0  END as Ord

case здесь не нужен. Просто 
Код
 "Field2" = "Field3" as Ord


Цитата(polin11 @  21.6.2018,  18:51 Найти цитируемый пост)
 при выполнении запроса планировщик пробежит ВСЕ записи

По дистинкту - да. Используй group by. Distinct - кака.

Автор: _zorn_ 22.6.2018, 19:02
На самом деле (акелла уверял) "group by" (ну и destinct соответсвенно) не детерменированны. Т.е. результат зависит от левой пятки движка мускуля. (Мы же про мускуль сейчас говорим ?)
А вообще нечего делать из мускуля оракл ) Что мешает в приложении нужные сравнения сделать ?

Автор: Akina 23.6.2018, 20:26
Цитата(_zorn_ @  22.6.2018,  20:02 Найти цитируемый пост)
 "group by" (ну и destinct соответсвенно) не детерменированны. 

Чё? бред какой-то, право слово... 

Цитата(polin11 @  21.6.2018,  18:51 Найти цитируемый пост)
затем отсортирует по Ord и выдаст первые 20 записей, то есть по времени и ресурсам будет аналогично, этому же запросу, но без LIMIT 20

Нет. Будь так - LIMIT 1,1 и LIMIT 100000,1 не различались бы практически по скорости, тогда как на деле разница будет не в разы - на порядки... На деле будут отсортированы первые 20, без сортировки остатних.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)