#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
Я пытаюсь рассчитать процентное изменение цены между днями. Поскольку дни не являются последовательными, я встраиваю в запрос вычисляемое поле, которое сообщает мне, какой сегодня относительный день (день 1, день 2 и т.д.). Чтобы сравнить сегодняшний день со вчерашним, я изменил номер вычисляемого дня на 1 в подзапросе. что я хочу сделать, так это объединить внутренний и внешний запрос в расчетный относительный день. Код, который я придумал, является:
SELECT TOP 11
P.Date,
(AVG(P.SettlementPri) - PriceY) / PriceY as PriceChange,
P.Symbol,
(RANK() OVER (ORDER BY P.Date desc)) as dayrank_Today
FROM OTE P
JOIN (SELECT TOP 11
C.Date,
AVG(SettlementPri) as PriceY,
(RANK() OVER (ORDER BY C.Date desc)) 1 as dayrank_Yest
FROM OTE C
WHERE C.ComCode = 'C-'
GROUP BY c.Date) C ON dayrank_Today = C.dayrank_Yest
WHERE P.ComCode = 'C-'
GROUP BY P.Symbol, P.Date
Если я пытаюсь выполнить запрос, я получаю сообщение об ошибке, указывающее, что dayrank_Today является недопустимым столбцом. Я пытался переименовать его, квалифицировать, выкрикивать оскорбления в его адрес, и я приседаю. Все еще ошибка.
Комментарии:
1. какую базу данных вы используете? sql server?
2. Немного сложно понять ваш вопрос. Можете ли вы предоставить нам структуру таблицы (только соответствующие поля), входные данные, желаемый результат запроса? В идеале вам нужно предоставить скрипт, который создает таблицы и заполняет их образцами данных.
3. @M.R.:
TOP
является SQL Server;RANK
означает SQL Server 20054.
AVG(P.SettlementPri)
это среднее значение поSymbol
amp;Date
, ноPriceY
это среднее значение только поDate
. Правильно ли это для сравнения двух? Это не ошибка?
Ответ №1:
Вы не можете выполнить выбор вычисляемого столбца, а затем использовать его в объединении. Вы можете использовать CTE, с которыми я не очень знаком, или вы можете просто выполнять выбор таблицы следующим образом:
SELECT
P.Date,
(AVG(AvgPrice) - C.PriceY) / C.PriceY as PriceChange,
P.Symbol,
P.dayrank_Today FROM
(SELECT TOP 11
ComCode,
Date,
AVG(SettlementPri) as AvgPrice,
Symbol,
(RANK() OVER (ORDER BY Date desc)) as dayrank_Today
FROM OTE WHERE ComCode = 'C-') P
JOIN (SELECT TOP 11
C.Date,
AVG(SettlementPri) as PriceY,
(RANK() OVER (ORDER BY C.Date desc)) 1 as dayrank_Yest
FROM OTE C
WHERE C.ComCode = 'C-'
GROUP BY c.Date) C ON dayrank_Today = C.dayrank_Yest
GROUP BY P.Symbol, P.Date
Комментарии:
1. M.R. Спасибо за быстрый ответ. Я попробовал ваш код, но, к сожалению, получаю сообщение об ошибке, в котором говорится, что цена не может быть привязана.
2. M.R. Я новичок в использовании Stackoverflow, поэтому я немного улучшаю ситуацию. Я предоставил дополнительную информацию о моем редактировании вашего ответа. Если это неправильный способ сделать что-то, просто дайте мне знать.
3. @GoingBaldBySql — было бы лучше обновить ваш вопрос, а не редактировать этот ответ. Однако не удаляйте существующий код и не давайте понять, что вы отвечаете на этот ответ.
4. @GoingBalBySql: Можете ли вы сказать мне, какая из дорогих привязок не выполняется? Скорее всего, я неправильно понял имена ваших полей … Т.Е. принадлежит ли PriceY таблице OTEИЛИ ее выделенному столбцу во второй таблице select?
5. @andriy M: правильно — @goingBaldBySql, вы должны добавить ‘group by’ к обоим подвыборкам..
Ответ №2:
Если возможно, рассмотрите возможность использования CTE, поскольку это очень упрощает задачу. Что-то вроде этого:
With Raw as
(
SELECT TOP 11 C.Date,
Avg(SettlementPri) As PriceY,
Rank() OVER (ORDER BY C.Date desc) as dayrank
FROM OTE C WHERE C.Comcode = 'C-'
Group by C.Date
)
select today.pricey as todayprice ,
yesterday.pricey as yesterdayprice,
(today.pricey - yesterday.pricey)/today.pricey * 100 as percentchange
from Raw today
left outer join Raw yesterday on today.dayrank = yesterday.dayrank 1
Очевидно, что это не включает символ, но его можно включить довольно легко.
Если использование синтаксиса ‘With’ не подходит, вы также можете использовать вычисляемые поля с внешним Applyhttp://technet.microsoft.com/en-us/library/ms175156.aspx
Хотя CTE будет означать, что вам нужно будет написать расчет цены только один раз, что намного чище
Приветствия
Ответ №3:
У меня была такая же проблема, и я нашел этот поток и нашел решение, поэтому я решил опубликовать его здесь.
Вместо того, чтобы использовать имя столбца в качестве параметра для ON, скопируйте инструкцию, которая в первую очередь присвоила вам имя colmun:
заменить:
ON dayrank_Today = C.dayrank_Yest
с:
ON (RANK() OVER (ORDER BY Date desc)) = C.dayrank_Yest
Конечно, вы вызываете неудовольствие Богов программирования, нарушая DRY, но вы могли бы быть прагматичными и упомянуть о дублировании в комментариях, что должно смягчить их гнев до легкого ворчания.