Функции даты в SQL Server

#sql-server #tsql #column-alias

#sql-сервер #tsql #псевдоним столбца

Вопрос:

Задача: отобразить имена клиентов и их заказы, сделанные в Пуне и Калькутте в марте месяце

Клиенты:

 CUST_ID    CUST_NAME    LOCATION
---------------------------------
   1          A         HYD
   2          B         PUNE
   3          C         DELHI
   4          D         KOLKATA
  

Заказы:

 ORDER_ID    CUST_ID AMOUNT  DATE
----------------------------------
100 3   1000    2019-03-22
101 2   2000    2019-03-12
103 1   3000    2019-04-11
104 2   5000    2019-04-10
105 3   6000    2019-02-18
  

Запрос:

 SELECT
    c.cust_name, c.location,
    CONVERT(VARCHAR(3), Date1, 100) AS Month
FROM
    customers1 c 
FULL OUTER JOIN
    orders o ON o.cust_id = c.cust_id
WHERE
    c.LOCATION = 'PUNE' OR c.LOCATION = 'KOLKATA'
GROUP BY 
    date1
HAVING
    Month = 'Mar'
  

Я получаю эту ошибку:

Сообщение 207, уровень 16, состояние 1, строка 7
Недопустимое имя столбца «Месяц»

Ответ №1:

Невозможно ссылаться на псевдоним в вашем предложении HAVING. По соображениям производительности я предлагаю фильтровать по номеру месяца, а не по аббревиатуре месяца.

 SELECT
     c.cust_name
    ,c.location
    ,CONVERT(varchar(3), Date1, 100) as Month
FROM customers1 c
    INNER JOIN orders o on o.cust_id=c.cust_id
WHERE
    (c.LOCATION='PUNE' or c.LOCATION='KOLKATA')
WHERE
    MONTH(Date1) = 3
  

Ответ №2:

То, что вы пытаетесь сделать, не работает в SQL Server, вы не можете использовать SELECT псевдоним в WHERE HAVING предложении or (так, как вы это делаете).

Кроме того, внешнее соединение не требуется. Вы можете выразить то, что хотите, используя apply :

 select c.cust_name, c.location, v.month
from customers1 c join
     orders o
     on o.cust_id = c.cust_id cross apply
     (values (CONVERT(varchar(3), Date1, 100))) v(Month)
where c.LOCATION in ('PUNE', 'KOLKATA') and
      v.month = 'Mar';
  

Я понятия не имею, почему у вас есть group by date1 . date1 отсутствует в select списке, и у вас нет функций агрегирования, поэтому агрегирование кажется ненужным.

Конечно, я бы упростил это до:

 select c.cust_name, c.location, 
       left(datename(month, date1))
from customers1 c join
     orders o
     on o.cust_id = c.cust_idv(Month)
where c.LOCATION in ('PUNE', 'KOLKATA') and
      month(date1) = 3;
  

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

1. Кажется глупым преобразовывать каждую дату в сокращение месяца и фильтровать по этому. Вместо этого я бы отфильтровал номер месяца и сбросил APPLY() . WHERE MONTH(Date1) = 3