Как можно отсортировать записи в SQL-запросе по двум полям, не применяя фильтрацию?

У меня возникла следующая идея: <br/> <br/> <pre><code class="sql">SELECT wp_posts.ID, wp_posts.post_title, wp_postmeta.meta_value FROM wp_posts
LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'pinned'
WHERE wp_posts.post_type  = 'partners' 
# AND wp_postmeta.meta_key = 'pinned' 
# ORDER BY wp_posts.post_date DESC LIMIT 25
ORDER BY IF(wp_postmeta.meta_value, CAST(wp_postmeta.meta_value AS UNSIGNED), wp_posts.post_date) ASC, wp_posts.post_date DESC
LIMIT 25</code></pre> <br/> <br/> Я основывался на решении от wp-kama, но решил не использовать обертку над WP_Query, так как она оказалась неэффективной. Вместо этого попробовал реализовать задачу на чистом SQL-запросе. <br/> <br/> Основная цель заключается в том, чтобы отсортировать записи по дате и произвольному полю "pinned", без фильтрации. Интересно, почему функции get_posts / WP_Query не позволяют это сделать, поскольку они отфильтровывают записи даже без указания meta_value, что меня не устраивает. Важный момент касается сортировки: сначала должны отображаться закрепленные записи в порядке ASC (хотя это не так критично, главное — чтобы они были первыми), а после — остальные "незакрепленные" по дате (или по любому другому полю в порядке ASC/DESC). Текущий вариант не позволяет это осуществить.
  • 22 февраля 2025 г. 16:24
Ответы на вопрос 2
Ваша задача заключается в том, чтобы отсортировать записи по двум полям: поле "pinned" и поле дату записи. Идея, которую вы используете, вполне разумна, однако есть несколько ключевых моментов, которые стоит учесть для корректной сортировки.

Сначала необходимо уточнить, как вы хотите обрабатывать записи с разными значениями поля "pinned". Вот пример SQL-запроса, который сортирует записи так, как вы описали:

```sql
SELECT wp_posts.ID, 
       wp_posts.post_title, 
       wp_postmeta.meta_value 
FROM wp_posts
LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id 
                     AND wp_postmeta.meta_key = 'pinned'
WHERE wp_posts.post_type = 'partners' 
ORDER BY 
    CASE 
        WHEN wp_postmeta.meta_value = '1' THEN 0 -- Если 'pinned' = 1, они будут первыми
        ELSE 1 
    END, 
    wp_posts.post_date DESC -- Остальные по дате
LIMIT 25
```

### Пояснения по запросу:

- **LEFT JOIN**: Мы используем LEFT JOIN для того, чтобы получить все посты с полем "pinned", и даже те, у которых это поле отсутствует.
  
- **CASE**: Используем оператор CASE для сортировки. Если `meta_value` (значение поля "pinned") равно '1', мы присваиваем ему значение 0, что делает его приоритетным при сортировке. Все остальные записи получат значение 1 и будут сортироваться после закрепленных.

- **wp_posts.post_date DESC**: После сортировки по "pinned", оставшиеся записи сортируются по дате (в порядке убывания).

- **LIMIT 25**: Ограничение на количество возвращаемых строк.

Этот запрос должен соответствовать вашим требованиям и корректно сортировать записи, причем сперва показывая закрепленные, а затем остальные по дате. Если вам нужно изменить порядок сортировки, достаточно поменять ASC на DESC или наоборот.
А все, в phpmyadmin на тыкал по колонкам как нужно, даже и думать не пришлось и получился такой вариант 

SELECT wp_posts.ID, wp_posts.post_title, wp_posts.post_date, wp_postmeta.meta_value FROM wp_posts 
LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'pinned' 
WHERE wp_posts.post_type = 'partners' 
ORDER BY `wp_postmeta`.`meta_value` DESC, `wp_posts`.`ID` DESC LIMIT 25


Хоть он конечно и не покрывает 100% задачу так как тут сортировка все равно общая какая то получается, мы сначала поднимает закрепленные а потом сортируем всё по ID, хотелось бы иметь возможность сортировать отдельно поднятые и все остальные по разному
Похожие вопросы