Как написать предложение WHERE, в котором одно из условий является результатом вычисляемого поля?

#sql #sql-server #sql-server-2012 #where-clause

#sql #sql-сервер #sql-server-2012 #предложение where

Вопрос:

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

 (SELECT avg(RateAmount)/1.15
FROM ReservationStayDate f
where f.ReservationStayID = a.ReservationStayID) AS 'Rate Amount Excl.VAT'
  

В том же запросе мне нужно исключить все данные, где RatePlan начинается с ‘CO’ И приведенный выше результат = 0

Другими словами, мое предложение WHERE должно выглядеть примерно так:

 AND NOT (d.rateplan like 'CO%' and (avg(RateAmount)/1.15)= 0)
  

Я получаю это сообщение об ошибке: недопустимое имя столбца ‘RateAmount’

Что здесь не так с синтаксисом?

ВОТ ПОЛНЫЙ ЗАПРОС:

 SELECT a.ReservationStayID,
   b.PropertyCode AS'Property',
   b.ReservationStatus AS 'Status',
   d.rsl_rateplan AS 'Rate Plan Code',
   b.MarketSegmentCode AS 'Market Segment',
   e.TravelAgencyTypeCode AS 'Source of Business',
   a.ArrivalDate AS 'Date of Arrival',
   a.DepartureDate AS 'Date of Departure',
   c.AdultCount AS 'Adult',
   c.ChildCount AS 'Child',
   b.GuestCount AS 'Guest',
   d.rsl_nationality AS 'Nationality',
   c.PMSConfirmationNumber,
   c.CurrencyCode As 'Currency',
   e.Name AS 'Tour Operator',
   e.CountryCode AS 'Market Code',
   g.CountryGroup AS 'Market',


 (SELECT avg(RateAmount)/1.15
  FROM ReservationStayDate f
  where f.ReservationStayID = a.ReservationStayID) AS 'Rate Amount Excl.VAT'

  FROM GuestNameInfo a
  JOIN GuestStaySummary b ON a.ReservationStayID = b.ReservationStayID
  LEFT JOIN ReservationStay c ON c.ReservationStayID = b.ReservationStayID
  LEFT JOIN P5RESERVATIONLIST d ON d.rsl_code = b.ReservationStayID
  LEFT JOIN TravelAgency e ON e.TravelAgencyID = c.TAProfileID
  LEFT JOIN Market g ON e.CountryCode = g.CountryCode

  WHERE a.PrimaryGuest=' ' and d.rsl_primaryguest=' '

  AND A.ARRIVALDATE <= '2013-09-30' AND A.DEPARTUREDATE > '2013-09-01'

  ORDER BY a.ReservationStayID
  

Комментарии:

1. Вы не можете ссылаться на RateAmount, поскольку у вас, вероятно, нет таблицы (ReservationStayDate) в вашем основном запросе. Если вы добавите его в свой основной запрос, то это приведет к созданию нескольких строк для каждого ReservationStayID, так что это не поможет. Вероятно, вам нужно выполнить запрос в два прохода, один для получения данных, а другой для фильтрации результатов?

2. Если я включу столбец из ReservationStayDate в свой основной запрос, то это сработает?

3. Какую СУБД вы используете?

Ответ №1:

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

 SELECT  a.SomeField,
        r.RateAmountExcVat
FROM    SomeTable AS a
        INNER JOIN SomeOtherTable AS d
            ON d.SomeField = a.SomeField
        --... Whatever else your query does...
        OUTER APPLY
        (   SELECT  RateAmountExcVat = AVG(RateAmount)/1.15
            FROM    ReservationStayDate AS f
            WHERE   f.ReservationStayID = a.ReservationStayID
        ) AS r
WHERE   NOT (d.RatePlan LIKE 'CO%' AND r.RateAmountExcVat = 0);
  

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

 SELECT  a.SomeField,
        r.RateAmountExcVat
FROM    SomeTable AS a
        INNER JOIN SomeOtherTable AS d
            ON d.SomeField = a.SomeField

        --... Whatever else your query does...

        LEFT JOIN 
        (   SELECT  ReservationStayID,
                    RateAmountExcVat = AVG(RateAmount)/1.15
            FROM    ReservationStayDate AS f
            GROUP BY ReservationStayID
        ) AS r
            ON r.ReservationStayID = a.ReservationStayID
WHERE   NOT (d.RatePlan LIKE 'CO%' AND r.RateAmountExcVat = 0);
  

Редактировать

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

 SELECT  a.ReservationStayID,
        b.PropertyCode AS [Property],
        b.ReservationStatus AS [Status],
        d.rsl_rateplan AS [Rate Plan Code],
        b.MarketSegmentCode AS [Market Segment],
        e.TravelAgencyTypeCode AS [Source of Business],
        a.ArrivalDate AS [Date of Arrival],
        a.DepartureDate AS [Date of Departure],
        c.AdultCount AS [Adult],
        c.ChildCount AS [Child],
        b.GuestCount AS [Guest],
        d.rsl_nationality AS [Nationality],
        c.PMSConfirmationNumber,
        c.CurrencyCode As [Currency],
        e.Name AS [Tour Operator],
        e.CountryCode AS [Market Code],
        g.CountryGroup AS [Market],
        f.RateAmountExclVAT AS [Rate Amount Excl.VAT]
FROM    GuestNameInfo a
        JOIN GuestStaySummary b 
            ON a.ReservationStayID = b.ReservationStayID
        LEFT JOIN ReservationStay c 
            ON c.ReservationStayID = b.ReservationStayID
        LEFT JOIN P5RESERVATIONLIST d 
            ON d.rsl_code = b.ReservationStayID
        LEFT JOIN TravelAgency e 
            ON e.TravelAgencyID = c.TAProfileID
        LEFT JOIN Market g 
            ON e.CountryCode = g.CountryCode
        LEFT JOIN
        (   SELECT  ReservationStayID, 
                    RateAmountExclVAT = AVG(RateAmount) / 1.15
            FROM    ReservationStayDate f
            GROUP BY f.ReservationStayID
        ) AS f
            ON f.ReservationStayID = a.ReservationStayID
WHERE   a.PrimaryGuest=' ' 
AND     d.rsl_primaryguest=' '
AND     A.ARRIVALDATE <= '2013-09-30' 
AND     A.DEPARTUREDATE > '2013-09-01'
AND     NOT (d.RatePlan like 'CO%' AND f.RateAmountExclVAT = 0)
ORDER BY a.ReservationStayID
  

Пара вещей, на которые стоит обратить внимание, это то, что я удалил ваш AS 'alias' синтаксис, поскольку использование литералов в качестве псевдонимов столбцов устарело. [Дальнейшее чтение в Вредные привычки для удара : использование AS вместо = для псевдонимов столбцов . Я бы также рекомендовал использовать псевдонимы таблицы значений, а не просто a, b, c и т.д.

Комментарии:

1. Спасибо GarethD… Я отредактировал сообщение с моим полным запросом. Не могли бы вы, пожалуйста, помочь?

2. Большое спасибо, GarethD! Высоко ценится! Не должен ли r.RateAmountExclVAT быть f.RateAmountExclVAT?

Ответ №2:

Возьмите существующий запрос и удалите этот фрагмент предложения WHERE:

 and (avg(RateAmount)/1.15)= 0
  

затем перепишите его следующим образом:

 SELECT * FROM (

<your original query>

) a WHERE a.[Rate Amount Excl.VAT] != 0;
  

Это не самый красивый способ сделать это, но без полного запроса…

Ответ №3:

Попробуйте это

 Select * from ReservationStayDate M
join
(SELECT f.ReservationStayID,avg(RateAmount)/1.15 R
FROM ReservationStayDate f
where f.ReservationStayID = a.ReservationStayID
and  d.rateplan not like 'CO%'
 group by    f.ReservationStayID
) AS E
on  E.ReservationStayID = M.ReservationStayID 
where E.r = 0
  

или попробуйте это

 (SELECT E.R
FROM ReservationStayDate f
join
    (SELECT f.ReservationStayID,avg(RateAmount)/1.15 R
    FROM ReservationStayDate f1
    whered.rateplan not like 'CO%'
     group by    f.ReservationStayID
    ) AS E
    on  E.ReservationStayID = F.ReservationStayID 
where E.r = 0

) AS 'Rate Amount Excl.VAT'
  

Комментарии:

1. Я не могу, потому что в своем запросе я извлекаю данные из других таблиц (в моем вопросе я показал только часть запроса), и мне нужна только средняя сумма ставки из таблицы ReservationStayDate.

2. В вашем подзапросе чего-то не хватает GROUP BY f.ReservationStayID . Этот ответ был бы существенно улучшен, если бы в нем было хотя бы одно предложение, объясняющее, какие изменения вы внесли и почему, вместо простого «Попробуйте это».

3. Я получаю это сообщение об ошибке: «Не удалось привязать состоящий из нескольких частей идентификатор «f.ReservationStayID»».