2016-04-21 5 views
0

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

Что разница в сумме полученных за каждый месяц 2004 г. по сравнению с 2003 годом?

Это то, что я до сих пор,

SELECT @2003 = (SELECT sum(amount) FROM Payments, Orders 
       WHERE YEAR(orderDate) = 2003 
       AND Payments.customerNumber = Orders.customerNumber 
        GROUP BY MONTH(orderDate)); 

    SELECT @2004 = (SELECT sum(amount) FROM Payments, Orders 
       WHERE YEAR(orderDate) = 2004 
       AND Payments.customerNumber = Orders.customerNumber 
        GROUP BY MONTH(orderDate)); 

    SELECT MONTH(orderDate), (@2004 - @2003) AS Diff 
      FROM Payments, Orders 
       WHERE Orders.customerNumber = Payments.customerNumber 
       Group By MONTH(orderDate); 

В выходе я получаю месяцев, но для Diff я получаю NULL, пожалуйста, помогите. Спасибо

+0

Попробуйте выполнить каждый из ваших первых двух запросов. (со второго выбора до точки с запятой) Возможно, «@ 2004» и «@ 2003» имеют разные значения, чем вы ожидаете. – starshine531

+0

Просто пробовал, что и все месяцы имеют разные значения между двумя годами. –

+0

Итак, каждый из этих запросов дает список из 12 значений? – starshine531

ответ

1

я не могу проверить это, потому что у меня нет таблиц, но попробовать что-то вроде этого:

SELECT a.orderMonth, (a.orderTotal - b.orderTotal) AS Diff 
FROM 
    (SELECT MONTH(orderDate) as orderMonth,sum(amount) as orderTotal 
    FROM Payments, Orders 
    WHERE YEAR(orderDate) = 2004 
    AND Payments.customerNumber = Orders.customerNumber 
     GROUP BY MONTH(orderDate)) as a, 
    (SELECT MONTH(orderDate) as orderMonth,sum(amount) as orderTotal FROM Payments, Orders 
    WHERE YEAR(orderDate) = 2003 
    AND Payments.customerNumber = Orders.customerNumber 
     GROUP BY MONTH(orderDate)) as b 
WHERE a.orderMonth=b.orderMonth 
+0

Поверьте мне, вы не хотите, чтобы 4000 строк создавали таблицы, но это сработало. Большое спасибо, я должен был попробовать подзапросы –

+0

Если мы получили три заказа от клиента в течение месяца и один платеж или два платежа и никаких заказов, запросы встроенного просмотра собираются создать полукартезианские продукты. Похоже, что вопрос был о «полученной сумме». Получены ли платежи в тот же месяц, когда размещен заказ? В том же году? Если этот запрос дает точный ответ на заданный вопрос, это был ужасный вопрос. Если это был хороший вопрос, то это ужасный ответ. – spencer7593

+0

Это базовое введение в базы данных и SQL-курс. Профессор (или его лаборант?) Просто задал нам ряд вопросов, чтобы мы могли запускать запросы, поэтому они - все ужасные вопросы. Но вы правы, мне нужно было изменить orderDate на paymentDate для более точного ответа, однако он не смотрит на результат, а сам запрос. Это просто что-то для нас, чтобы разобраться в лабораториях и получить sql exp. (BTW нам разрешено иметь внешнюю помощь для лабораторий и рекомендуется задавать вопросы для самостоятельного обучения) –

0

Я думаю, что это проблема:
В @ 2003 и @ 2004 вы выбираете только сумму. И даже если вы группируете по месяцу, вы по-прежнему выбираете один столбец, то есть каждая строка не говорит, в каком месяце он выбирает. Поэтому, когда вы пытаетесь вычесть SQL, запрашивается, какая строка в @ 2003 должна быть вычтена из @ 2004.
Так что я думаю, что решение состоит в том, чтобы выбрать месяц с суммой и сделать вычитание позже в зависимости от месяца.

0

Q: Как вычесть два объявлены переменные в MySQL.

A: Вы должны сначала ЗАКАЗАТЬ их. В контексте хранимой программы MySQL. Но эти имена переменных не начинались с символа знака. Имена переменных, начинающиеся с знака at @, являются определяемыми пользователем переменными. И для них нет инструкции DECLARE, мы не можем объявить их конкретным типом.

Чтобы вычесть их в SQL заявление

SELECT @foo - @bar AS diff 

Обратите внимание, что MySQL пользовательские переменные скалярные значения.

Назначение значения пользовательской переменной в инструкции SELECT выполняется с помощью оператора присваивания стиля Pascal : =. В выражении в выражении SELECT знак равенства является оператором сравнения равенства.

В качестве простого примера того, как присвоить значение в заявлении SQL SELECT

SELECT @foo := '123.45' ; 

В ОПАХ запросов нет присваивания делается. Знак равенства - это сравнение, скалярного значения с возвратом из подзапроса. Действительно ли эти первые операторы работают без ошибки?

Определенные пользователем переменные, вероятно, не нужны для решения этой проблемы.

Вы хотите вернуть сколько строк? Похоже, вы хотите один за каждый месяц. Мы предположим, что к «году» мы имеем в виду календарный год, как и в январе-декабре. (Возможно, мы захотим проверить это предположение. Именно поэтому мы не слишком поздно оповещаем, что речь шла о «финансовом году», который проходил с июля по июнь или что-то в этом роде.)

Как мы можем получить список месяцев? Похоже, у тебя есть начало. Мы можем использовать GROUP BY или DISTINCT.

Вопрос был ...«Какая разница в полученной суммы ...»

Итак, мы хотим, чтобы составить получил. Будет ли это сумма платежей мы получили? Или количество заказов, которые мы получили? (А мы принимая заказы и получать платежи? Или мы размещение заказов и делает платежи?)

Когда я думаю о «полученная сумма», я имею в виду с точки зрения дохода.

Учитывая только две таблицы, которые мы видим, я думаю, мы заполнения заказов и приема платежей. (Вероятно, я хочу проверить это, поэтому, когда я закончил, мне не сказали ... «о, мы имели в виду количество заказов, которые мы получили» и/или «таблица платежей - это платежи, которые мы сделали, сумма, которую мы получили «находится в какой-то другой таблице»

Мы предполагаем, что есть столбец, который идентифицирует «дату», в которой был получен платеж, и что тип данных этого столбца - DATE (или DATETIME или TIMESTAMP), какой-то тип, который мы можем достоверно определить, что «месяц» платеж был получен в.

Чтобы получить список месяцев, которые мы получили платежи в 2003 году ...

SELECT MONTH(p.payment_received_date) 
    FROM payment_received p 
    WHERE p.payment_received_date >= '2003-01-01' 
    AND p.payment_received_date < '2004-01-01' 
    GROUP BY MONTH(p.payment_received_date) 
    ORDER BY MONTH(p.payment_received_date) 

Tha t должен получить нас двенадцать строк. Если мы не получили никаких платежей в течение определенного месяца. Тогда мы можем получить только 11 строк. Или 10. Или, если мы не получили никаких платежей за весь 2003 год, мы не получим никаких строк назад.

Для обеспечения производительности мы хотим, чтобы наши предикаты (условия в столбцах WHERE clause0 ссылались на нулевые столбцы.С помощью соответствующего индекса MySQL эффективно использует операцию сканирования диапазона индексов.Если мы обертываем столбцы в функцию, например

WHERE YEAR(p.payment_received_date) = 2003 

при том, что мы будем вынуждать MySQL, чтобы оценить эту функцию на каждый листать строки в таблице, а затем сравнить отдачу от функции к буквальному. мы предпочитаем не делать это сделать, и контрольные голые столбцы в предикатах (условия в предложении WHERE).

Мы могли бы повторить тот же запрос, чтобы получить платежи, полученные в 2004 году. Все, что нам нужно сделать, это изменить литералы даты.

Или мы можем собрать все строки в 2003 и 2004 годах вместе и свернуть это в список отдельных месяцев.

Мы можем использовать условную агрегацию. Поскольку мы используем календарные годы, я использую ярлык YEAR() (а не проверку диапазона). Здесь мы не так заботимся о том, чтобы использовать выражение в столбце.

SELECT MONTH(p.payment_received_date) AS `mm` 
    , MAX(MONTHNAME(p.payment_received_date)) AS `month` 
    , SUM(IF(YEAR(p.payment_received_date)=2004,p.payment_amount,0)) AS `2004_month_total` 
    , SUM(IF(YEAR(p.payment_received_date)=2003,p.payment_amount,0)) AS `2003_month_total` 
    , SUM(IF(YEAR(p.payment_received_date)=2004,p.payment_amount,0)) 
    - SUM(IF(YEAR(p.payment_received_date)=2003,p.payment_amount,0)) AS `2004_2003_diff` 
    FROM payment_received p 
WHERE p.payment_received_date >= '2003-01-01' 
    AND p.payment_received_date < '2005-01-01' 
GROUP 
    BY MONTH(p.payment_received_date) 
ORDER 
    BY MONTH(p.payment_received_date) 

Если это проблема домашнего задания, я настоятельно рекомендую вам работать над этой проблемой самостоятельно. Существуют другие шаблоны запросов, которые возвращают эквивалентный результат.

+0

Спасибо, вы положили много времени на этот ответ, и я многому научился у него –

+0

Единственный способ, которым запрос с полу- соединение таблицы платежей и таблица заказов приходят с «правильным» ответом: если CustomerNumber гарантированно будет * уникальным * в любом заказе или платежах. – spencer7593

+0

ЗаказчикНомера автоматически увеличивает и является Первичным ключом таблицы Клиенты и внешний ключ как в Платежах, так и в Заказе. Таблица –

Смежные вопросы