Mysql Query, который требует вычитания полей, на которые нельзя ссылаться - PullRequest
0 голосов
/ 24 февраля 2011

Наша база данных хранит заказы клиентов в двух таблицах: заказы клиентов и заказы клиентов. Среди других полей есть поле customerorders.type, которое определяет (будучи = 1 или = 2) если этот заказ клиента является счетом или кредиткой.

В настоящее время у нас есть отчет, в котором перечисляется количество проданных единиц, прибыль и т. Д., Но в его текущем запросе отображается только общее количество проданных единиц за период, т. Е. Не вычитается количество кредитов, если таковые имеются. Вот его sql и пример результатов, которые он генерирует:

(извиняюсь за массивный запрос, следующий за:))

SELECT l.name AS locationname
, sr.name AS salesrepname
, ct.name AS customertypename
, c.name AS customername
, c.id AS customer_id
, c.code
, s.name AS suppliername
, p.description AS productname
, p.id AS product_id
, p.unitofmeasure
, SUM(col.vatableprice) AS totalsales
, SUM(col.vatprice) AS vat
, SUM(col.quantity) AS totalitems
, SUM(col.quantity * col.costprice) AS totalsalecost
, SUM(col.vatableprice) - SUM(col.quantity * col.costprice) AS totalprofit
,(
     SELECT SUM(col2.vatableprice) AS totalsales 
     FROM customerorders AS co2 
     LEFT JOIN customerorderlines AS col2 ON col2.customerorder_id = co2.id
     LEFT JOIN customers AS c2 ON c2.id = co2.customer_id
     LEFT JOIN locations AS l2 ON l2.id = c2.location_id
     LEFT JOIN customertypes AS ct2 ON ct2.id = c2.customertype_id
     LEFT JOIN salesreps AS sr2 ON sr2.id = c2.salesrep_id
     LEFT JOIN products AS p2 ON p2.id = col2.product_id
     LEFT JOIN suppliers AS s2 ON s2.id = p2.supplier_id
     WHERE c.salesrep_id = c2.salesrep_id
     AND co2.type = 2 AND p2.supplier_id = 179
     AND co2.orderdate >= '2010-01-01 00:00:00'
     AND co2.orderdate <= '2010-02-01 23:59:59'
) AS credits 
,(
    SELECT SUM(col2.vatprice) AS totalvat FROM customerorders AS co2
    LEFT JOIN customerorderlines AS col2 ON col2.customerorder_id = co2.id
    LEFT JOIN customers AS c2 ON c2.id = co2.customer_id
    LEFT JOIN locations AS l2 ON l2.id = c2.location_id
    LEFT JOIN customertypes AS ct2 ON ct2.id = c2.customertype_id
    LEFT JOIN salesreps AS sr2 ON sr2.id = c2.salesrep_id
    LEFT JOIN products AS p2 ON p2.id = col2.product_id
    LEFT JOIN suppliers AS s2 ON s2.id = p2.supplier_id
    WHERE c.salesrep_id = c2.salesrep_id
    AND co2.type = 2
    AND p2.supplier_id = 179
    AND co2.orderdate >= '2010-01-01 00:00:00'
    AND co2.orderdate <= '2010-02-01 23:59:59'
) AS creditsvat

FROM customerorders AS co
LEFT JOIN customerorderlines AS col ON col.customerorder_id = co.id
LEFT JOIN customers AS c ON c.id = co.customer_id
LEFT JOIN locations AS l ON l.id = c.location_id
LEFT JOIN customertypes AS ct ON ct.id = c.customertype_id
LEFT JOIN salesreps AS sr ON sr.id = c.salesrep_id
LEFT JOIN products AS p ON p.id = col.product_id
LEFT JOIN suppliers AS s ON s.id = p.supplier_id
WHERE co.status_v = 5 
AND co.type = 1
AND p.supplier_id = 179
AND co.orderdate >= '2010-01-01 00:00:00' AND co.orderdate <= '2010-02-01 23:59:59'
GROUP BY c.salesrep_id

Который в данном случае (группировка и т. Д. Определяется кодом приложения) генерирует отчет «на каждого представителя по продажам»:

Rep | TotalItems | SalesValue| CostOfSales | Profit   | VAT      | Credits | Credits(VAT)
Rep1| 937        | £5796.49  | £3606.49    | £2190.00 | £1013.73 | £220.12 | £38.57
Rep2| 1905       | £11695.09 | £7314.95    | £4380.14 | £2045.32 | £268.85 | £47.00
Rep3| 1074       | £6346.61  | £3950.53    | £2396.08 | £1109.76 | £54.89  | £9.57
Rep4| 2687       | £16129.42 | £10171.65   | £5957.77 | £2820.46 | £839.15 | £146.78

Итак, проблема заключается в том, что TotalItems - это абсолютное количество проданных товаров (все заказчики типа = 1). В поле «Кредиты» отображается общая стоимость товаров за период типа = 2, т.е. У TotalItems должно быть вычтено количество кредитов, чтобы сразу было видно, что на самом деле было продано, и, конечно, все остальные поля нуждаются в том, чтобы их коллеги по кредитам тоже вычитали друг друга, чтобы они отражали правильные суммы для проданных товаров.

Сначала я подумал, что это будет простой модификацией существующего запроса, но потом заметил, что не могу ссылаться на псевдонимы подзапроса в select, поэтому я переписал весь запрос, используя JOIN (SELECT ....) AS sales / JOIN (SELECT .....) AS кредиты, чтобы я мог затем ссылаться на sales.qty и credits.qty из SELECT в верхней части запроса, но затем это не масштабировалось, если только вы не выполняли небольшие запросы.

Вот как далеко я добрался:

(Да, я здесь запрашиваю разные вещи ... это, по сути, самая простая форма запроса: продажи / кредиты для одного продукта)

SELECT sr.name AS salesrepsname
,l.name AS locationname
,sup.name AS suppliername
,p.description AS productname
,sales.qty AS sold
,credits.qty AS credits
,sales.qty - credits.qty AS actualsold
FROM
customerorders co
LEFT JOIN customerorderlines col ON col.customerorder_id = co.id
LEFT JOIN customers c ON c.id = co.customer_id
LEFT JOIN products p ON p.id = col.product_id
LEFT JOIN salesreps sr ON sr.id = c.salesrep_id
LEFT JOIN locations l ON l.id = c.location_id
LEFT JOIN suppliers sup ON sup.id = p.supplier_id 
JOIN (SELECT SUM(col.quantity) AS qty,
SUM(col.vatableprice) AS total FROM customerorderlines col
LEFT JOIN customerorders co ON co.id = col.customerorder_id
WHERE col.product_id = 27642 AND co.type = 1)
AS sales
JOIN (SELECT SUM(col2.quantity) AS qty FROM customerorderlines col2
LEFT JOIN customerorders co2 ON co2.id = col2.customerorder_id
WHERE col2.product_id = 27642 AND co2.type = 2) AS credits
WHERE col.product_id = 27642
GROUP BY c.salesrep_id

Так что я должен признать, что я немного застрял, совсем не разбираясь в mysql.

Любые предложения очень приветствуются, и, пожалуйста, не стесняйтесь указывать мне на любую литературу по продвинутым запросам и присоединениям, которые я должен читать.

Ура!

1 Ответ

1 голос
/ 24 февраля 2011

Я думаю, что уловка, которую вы можете искать, заключается в следующем. В любом конкретном запросе / подзапросе, который вы хотите исправить, используйте некоторый SQL-код, подобный этому, выбирая все строки, независимо от того, является ли это счет-фактура или кредитная заметка, и суммируя значение, которое является либо положительным, либо отрицательным, в зависимости от того, каков порядок / деньги происходит:

SELECT 
  SUM(CASE WHEN co.type = 1 THEN col.quantity ELSE -col.quantity END)
FROM
  ...

Получите это? Вы забираете все свои строки заказа назад, но когда вы делаете сумму, вы складываете положительные кредиты и отрицательные дебеты, чтобы получить реальную сумму за одну операцию.

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