Как сохранить значение подзапроса MySQL и использовать его в предложении WHERE внешнего запроса - PullRequest
2 голосов
/ 23 февраля 2012

У меня есть таблица MySQL под названием «ad», в которой хранится серия рекламных объявлений для сайта электронной коммерции домашних животных. Это структура указанной таблицы:

ad * * 1004

ID: уникальный идентификатор объявления.

Пользователь: идентификатор пользователя, опубликовавшего объявление

Животное: тип животного

Раса: раса животных

Название

Цена: цена объявления

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

SELECT * FROM `ad` AS `out_ad`
WHERE `out_ad`.`user` = {iduser} AND
`out_ad`.`price` > (
     SELECT AVG(`price`) FROM `ad` AS `in_ad`
     WHERE `in_ad`.`user` <> `out_ad`.`user`
     AND `in_ad`.`animal` = `out_ad`.`animal`
     AND `in_ad`.`race` = `out_ad`.`race`
)

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

SELECT *, ( SELECT AVG(`price`) FROM `ad` AS `in_ad`WHERE `in_ad`.`user` <> out_ad`.`user`
         AND `in_ad`.`animal` = `out_ad`.`animal`
         AND `in_ad`.`race` = `out_ad`.`race`
         ) AS `avg_precio`
FROM `ad` AS `out_ad`
WHERE `out_ad`.`user` = {iduser}

Опять же, это работает нормально, но не сравнивает, какая запись выше среднего, я попытался использовать псевдоним подзапроса в предложении WHERE моего внешнего запроса, но он дает мне эту ошибку MySQL: # 1054 - Неизвестный столбец ' avg_price 'in' where clause '

SELECT *, ( SELECT AVG(`price`) FROM `ad` AS `in_ad`WHERE `in_ad`.`user` <> out_ad`.`user`
         AND `in_ad`.`animal` = `out_ad`.`animal`
         AND `in_ad`.`race` = `out_ad`.`race`
         ) AS `avg_price`
FROM `ad` AS `out_ad`
WHERE `out_ad`.`user` = {iduser} AND `out_ad`.`price` > `out_ad`.`avg_price`

Есть ли способ сохранить внутренний запрос, чтобы он возвращался в виде столбца и одновременно использовался в операторе WHERE?

Спасибо за чтение!

Ответы [ 3 ]

1 голос
/ 23 февраля 2012

Вы также можете заключить запрос во внешний и перенести туда проблемное условие:

SELECT *
FROM
  ( SELECT *, ( SELECT AVG(`precio`) 
                FROM `ad` AS `in_ad`
                WHERE `in_ad`.`user` <> out_ad`.`user`
                  AND `in_ad`.`animal` <> `out_ad`.`animal`
                  AND `in_ad`.`race` <> `out_ad`.`race`
             ) AS `avg_price`
    FROM `ad` AS `out_ad`
    WHERE `out_ad`.`user` = {iduser} 
  ) AS as
WHERE  price > avg_price
1 голос
/ 23 февраля 2012

Я бы сделал что-то, что выглядит чудовищно, но останься со мной немного

SELECT
    ad.*,
    ad_avg.price_average
FROM ad
INNER JOIN (
    -- Get the average price per animal
    SELECT
        ad.animal,
        ad.race,
        AVG(ad.price) AS price_average
    FROM ad
    INNER JOIN (
        -- Make sure it only gets ads that the user has selected
        SELECT DISTINCT
            animal,
            race
        FROM ad
        WHERE user = {iduser}
    ) AS ad_usr
    ON ad_usr.animal = ad.animal
    AND ad_usr.family = ad.family
    GROUP BY ad.animal, ad.race
) AS ad_avg
-- Join the averages onto ad
ON ad.animal = ad_avg.animal
AND ad.race = ad_avg.race
AND ad.price > ad_avg.price_average
WHERE ad.user = {iduser}

Итак, начиная с [QRY1] , выберите комбинации животных / расы, в которых пользователь размещает рекламу, чтобы ограничить типы объявлений, которые усредняются по причинам эффективности

        SELECT DISTINCT
            animal,
            race
        FROM ad
        WHERE user = {iduser}

Теперь уровень вверх, [QRY2] , здесь используются животные и расы с [QRY1] и определяются общие средние цены для них.

    SELECT
        ad.animal,
        ad.race,
        AVG(ad.price) AS price_average
    FROM ad
    INNER JOIN (
        [QRY1]
    ) AS ad_usr
    ON ad_usr.animal = ad.animal
    AND ad_usr.family = ad.family
    GROUP BY ad.animal, ad.race

А теперь вернемся к запросу верхнего уровня, это объединит таблицу средних значений в таблицу объявлений, выбрав все объявления желаемого пользователя, успех!

SELECT
    ad.*,
    ad_avg.price_average
FROM ad
INNER JOIN (
    [QRY2]
) AS ad_avg
-- Join the averages onto ad
ON ad.animal = ad_avg.animal
AND ad.race = ad_avg.race
AND ad.price > ad_avg.price_average
WHERE ad.user = {iduser}

И только потому, что у меня такое настроение

Я не пробовал приведенный ниже запрос, но теоретически он должен делать почти то же самое, однако требует, чтобы идентификатор пользователя был указан только один раз, и соединяет самый внутренний [QRY1] выбор в кортеже в [QRY2] ГДЕ утверждение. Возможно, стоит попробовать, если он более эффективен, трудно сказать, не проверяя ваш набор данных

SELECT
    ad.*,
    ad_avg.price_average
FROM ad
INNER JOIN (
    SELECT
        ad.animal,
        ad.race,
        AVG(ad.price) AS price_average
    FROM ad
    WHERE (ad.animal,ad.race) IN (
        SELECT DISTINCT
            ad.animal,
            ad.race
        FROM ad,(SELECT @iduser := {iduser}) v
        WHERE ad.user = @iduser
    )
    GROUP BY ad.animal,ad.race
) AS ad_avg
ON (ad.animal,ad.race) = (ad_avg.animal,ad_avg.race)
AND ad.price > ad_avg.price_average
WHERE ad.user = @iduser
0 голосов
/ 07 декабря 2013

Прежде всего, с логической точки зрения, я бы предложил убрать in_ad`.`user` <> `out_ad`.`user условие при расчете AVG(price).

Если цена одного пользователя выше средней цены (рассчитанной с учетом этого пользователя), то ее цена выше средней цены, рассчитанной без этого пользователя. Наоборот.

После удаления этого условия вы даже можете создать таблицу:

create table avgprice as
  select animal, race, AVG(price) from ad group by animal, race

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...