Это происходит внутри WordPress, но это общий вопрос MySQL.
Есть две таблицы, одна из которых содержит посты, другая метаданные, связанные по ID.
post_title | ID post_id | meta_key | meta_value
-----------+--- --------+----------+-----------
title | 1 1 | key_1 | aaa
-----------+--- --------+----------+-----------
title | 2 1 | key_2 | bbb
--------+----------+-----------
1 | mykey | 1
--------+----------+-----------
2 | key_n | ccc ddd
Я пытаюсь упорядочить результаты по некоторому значению столбца, которое может быть установлено не для всех строк. По сути, я хочу сначала увидеть строки с этой парой столбец/значение, а затем все остальные. С каждым сообщением могут быть связаны некоторые метаданные, основанные на парах meta_key
и meta_value
. Для одного сообщения может быть больше ключей, и они не должны включать тот, по которому я хочу сортировать.
Проблема в том, что использование запроса MySQL с WHERE meta_key = mykey
исключит все сообщения, в которых этот ключ не существует. Итак, что мне нужно, так это способ отобразить значение по умолчанию для всех тех сообщений, где этого мета-ключа не существует.
Первый шаг: легко выбрать все строки с определенным мета_ключом:
SELECT
p.ID, p.post_title, p.post_type, p.post_date, m.meta_value
FROM wp_posts AS p
LEFT JOIN wp_postmeta AS m ON p.ID = m.post_id
WHERE
m.meta_key = 'mykey'
Второй шаг: как выбрать все строки, в которых этот мета_ключ не существует?
Вот что я имею в виду, но это, вероятно, плохое решение:
SELECT
p.ID, p.post_title, p.post_type, p.post_date, "some_default"
FROM wp_posts AS p
WHERE
p.ID NOT IN (
SELECT
p.ID
FROM wp_posts AS p
LEFT JOIN wp_postmeta AS m ON p.ID = m.post_id
WHERE
m.meta_key = 'mykey'
)
Третий шаг: показать объединенные результаты. Это может быть UNION
из обоих запросов выше.
Я уверен, что должно быть лучшее решение. Что еще более важно, я не знаю, как указать дополнительные параметры - например. g., сначала найдите все сообщения с заданным мета-ключом, заголовком, категорией и т. д., а затем упорядочите их по указанному mykey
, как указано выше.
ПОСЛЕДНИЕ РЕДАКТИРОВАНИЯ
Если кому-то интересно, вот окончательное решение в контексте. Ответ RedFilter сделал это возможным, еще раз спасибо.
SELECT p1.ID, p1.post_title, p1.post_type, p1.post_date, m1.meta_value AS meta1, meta2
FROM wp_posts AS p1
LEFT JOIN wp_postmeta AS m1 ON m1.post_id = p1.ID
LEFT JOIN wp_term_relationships AS tr0 ON tr0.object_id = p1.ID
LEFT JOIN wp_term_taxonomy AS tt0 ON tr0.term_taxonomy_id = tt0.term_taxonomy_id
LEFT JOIN wp_terms AS t0 ON tt0.term_id = t0.term_id
LEFT JOIN
(
SELECT
p.ID, IF (m.meta_value = 'on', 1, 0) AS meta2
FROM wp_posts AS p
LEFT JOIN wp_postmeta AS m
ON p.ID = m.post_id
and m.meta_key = 'mykey'
) as extra
ON extra.ID = p1.ID
WHERE 1 = 1
AND m1.meta_key = 'some-other-meta-key'
AND p1.post_type IN ('post', 'some-custom-post-type')
AND tt0.taxonomy = 'some-taxonomy'
AND t0.term_id = 'some-id'
ORDER BY meta2 DESC, meta1 ASC, p1.post_date DESC