MySQL 'переменная' не доступна в CASE - PullRequest
1 голос
/ 10 августа 2011

Основная проблема в том, что я пытаюсь использовать счетчик подзапроса в качестве переменной в своем операторе WHERE CASE, но он не позволяет мне его использовать. У меня это работает, когда я помещаю оператор SELECT COUNT (id) ... в область WHERE, но - если я это сделаю, мне придется включить его 3-4 раза вместо одного раза, если можно положить его в SELECT.

Ниже приведен модифицированный пример запроса, объясняющий мою проблему. Это не тот запрос, который я использую, но он выдает ту же ошибку, что и мой гораздо более длинный / более сложный запрос:

Ошибка:

[Err] 1054 - Неизвестный столбец 'matched_sections' в 'предложении where'

Запрос:

SELECT
    articles.id,
    (SELECT COUNT(id) FROM site_areas_site_sections WHERE
        site_areas_site_sections.site_area_id = 8) AS matched_sections
FROM
    articles
LEFT JOIN
    articles_site_sections ON articles_site_sections.article_id = articles.id
LEFT JOIN
    site_areas_site_sections ON articles_site_sections.site_section_id = 
    site_areas_site_sections.site_section_id
WHERE
    (CASE
        WHEN
            matched_sections > 0
        THEN
           site_sections.id = site_areas_site_sub_sections.site_sub_section_id
        END
)

Ответы [ 3 ]

1 голос
/ 10 августа 2011

Из-за порядка, в котором обрабатываются элементы оператора SQL, matched_sections не определяется во время оценки предложения WHERE.

Возможно, вы захотите предварительно заполнить счетчики используйте это в своем запросе.

DECLARE matched_sections INT;

SET matched_sections = (SELECT COUNT(id) 
                            FROM site_areas_site_sections 
                            WHERE site_areas_site_sections.site_area_id = 8);
1 голос
/ 10 августа 2011

Проблема в том, что когда MySQL начинает анализировать ваш запрос, предложение SELECT является последним анализируемым битом.Поэтому, когда он проходит через предложение WHERE, matched_sections еще не существует (потому что предложение SELECT еще не изучено.

Просто взгляните на него, вы можете попробоватьвот так (хотя я думаю, что кто-то сможет придумать что-нибудь более изящное):

SELECT
    articles.id,
    matched_sections.count
FROM
    articles
LEFT JOIN
    articles_site_sections ON articles_site_sections.article_id = articles.id
LEFT JOIN
    site_areas_site_sections ON articles_site_sections.site_section_id = 
    site_areas_site_sections.site_section_id, 
(SELECT COUNT(id) as count FROM site_areas_site_sections WHERE
        site_areas_site_sections.site_area_id = 8) matched_sections
WHERE
    (CASE
        WHEN
            matched_sections.count > 0
        THEN
           site_sections.id = site_areas_site_sub_sections.site_sub_section_id
        END
)
0 голосов
/ 10 августа 2011

Как вам уже сказали, ошибка связана с тем, что предложение WHERE ничего не знает о значениях, которые вы на самом деле выбираете, поскольку оно оценивается до предложения SELECT.

В общем, вы можете решить эту проблему, используя весь запрос как производную таблицу, и в этом случае псевдоним matched_sections становится доступным для внешнего запроса:

SELECT
  id,
  matched_section
FROM (
  SELECT
      articles.id,
      (SELECT COUNT(id) FROM site_areas_site_sections WHERE
          site_areas_site_sections.site_area_id = 8) AS matched_sections
  FROM
      articles
  LEFT JOIN
      articles_site_sections ON articles_site_sections.article_id = articles.id
  LEFT JOIN
      site_areas_site_sections ON articles_site_sections.site_section_id = 
      site_areas_site_sections.site_section_id
) s
WHERE
  CASE
    WHEN matched_sections > 0
    THEN …
  END

Если ваше исходное условие содержит ссылки на столбцы, которые не предназначены для извлечения, вам необходимо добавить их в список выбора производной таблицы, чтобы вы могли использовать их в условии внешнего запроса.

В тех случаях, когда подзапрос не коррелирует с основным запросом (и это не в вашем примере), решения @Joe и @Dirk, возможно, являются лучшими вариантами, чем приведенное выше предложение.

...