СОЕДИНЕНИЕ SQL, GROUP BY на трех таблицах для получения общих количеств

В Ada (и я верю большинству других Полученных из Алгола языков) завершающееся условие "для" цикла оценено только однажды, в начале цикла. Например, предположите, что у Вас есть следующий код в Ada

q := 10;
for i in 1..q loop
    q := 20;
    --// Do some stuff
end loop;

, которого Этот цикл выполнит итерации точно 10 раз, потому что q равнялся 10 когда запущенный цикл. Однако, если я пишу на вид эквивалентный цикл в C:

q = 10;
for (int i=0;i<q;i++) {
   q = 20;
   // Do some stuff
}

Тогда цикл выполняет итерации 20 раз, потому что q был изменен на 20 к тому времени, когда я стал достаточно крупным для него для имения значение.

путь C более гибок, конечно. Однако это имеет довольно много отрицательных последствий. Очевидное - то, что программа должна потратить впустую усилие, перепроверяющее, что цикл обусловливает каждый цикл. Хороший оптимизатор мог бы быть достаточно умным для работы вокруг проблемы в простых случаях как это, но что происходит, если "q" является глобальным, и "делают некоторый материал" включает вызов процедуры (и таким образом в теории мог изменить q)?

неопровержимый факт - то, что мы просто знаем путь [еще 112] о цикле Ada, чем мы делаем о цикле C. Это означает, что с тем же уровнем аналитики и усилия в его оптимизаторе, Ada может сделать намного лучшее задание оптимизации. Например, компилятор Ada знает, что может заменить весь цикл 10 копиями содержания, неважно, каково то содержание. Оптимизатор C должен был бы исследовать и проанализировать содержание.

Это - на самом деле только один из многих путей, где дизайн синтаксиса C зажимает в тиски компилятор.

12
задан Raging Bull 24 April 2014 в 19:14
поделиться

4 ответа

Я не уверен, что понял вас, но это может быть то, что вы ищете:

SELECT i.invoiceid, sum(case when i.amount is not null then i.amount else 0 end), sum(case when i.amount is not null then i.amount else 0 end) - sum(case when p.amount is not null then p.amount else 0 end) AS amountdue
FROM invoices i
LEFT JOIN invoicepayments ip ON i.invoiceid = ip.invoiceid
LEFT JOIN payments p ON ip.paymentid = p.paymentid
LEFT JOIN customers c ON p.customerid = c.customerid
WHERE c.customernumber = '100'
GROUP BY i.invoiceid

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

15
ответ дан 2 December 2019 в 05:55
поделиться

Во-первых, разве не должно быть CustomerId в таблице Invoices? Как бы то ни было, вы не можете выполнить этот запрос для счетов-фактур, по которым еще нет платежей. Если в счете-фактуре нет платежей, этот счет-фактура даже не будет отображаться в выводе запроса, даже если это внешнее соединение ...

Кроме того, когда покупатель производит платеж, как узнать, какой счет-фактура прикрепить к? Если единственный способ - использовать InvoiceId в квитанции, которая поступает с платежом, то вы (возможно, ненадлежащим образом) связываете счета-фактуры с заказчиком, который их оплатил, а не с заказчиком, который их заказал .... (Иногда счет может быть оплачен кем-то, кроме клиента, заказавшего услуги)

2
ответ дан 2 December 2019 в 05:55
поделиться

Большое спасибо за ответы!

Saggi Malachi, этот запрос, к сожалению, суммирует сумму счета в случаях, когда существует более одного платежа. Допустим, есть два платежа по счету на 39 долларов: 18 и 12 долларов. Таким образом, вместо того, чтобы получить результат, который выглядит примерно так:

1   39.00   9.00

Вы получите:

1   78.00   48.00

Charles Bretana, в ходе сокращения моего запроса до простейшего из возможных запросов я (по глупости) пропустил дополнительную таблицу, customerinvoices, которая обеспечивает связь между клиентами и счетами. Это можно использовать для просмотра счетов-фактур, по которым не производились платежи.

После долгих усилий я думаю, что следующий запрос вернет то, что мне нужно:

SELECT DISTINCT i.invoiceid, i.amount, ISNULL(i.amount - p.amount, i.amount) AS amountdue
FROM invoices i
LEFT JOIN invoicepayments ip ON i.invoiceid = ip.invoiceid
LEFT JOIN customerinvoices ci ON i.invoiceid = ci.invoiceid
LEFT JOIN (
  SELECT invoiceid, SUM(p.amount) amount
  FROM invoicepayments ip 
  LEFT JOIN payments p ON ip.paymentid = p.paymentid
  GROUP BY ip.invoiceid
) p
ON p.invoiceid = ip.invoiceid
LEFT JOIN payments p2 ON ip.paymentid = p2.paymentid
LEFT JOIN customers c ON ci.customerid = c.customerid
WHERE c.customernumber='100'

Вы, ребята, согласны?

6
ответ дан 2 December 2019 в 05:55
поделиться

У меня есть совет для тех, кто хочет получить различные агрегированные значения из одной таблицы.

Допустим, у меня есть таблица с пользователями и таблица с баллами, которые приобретают пользователи. Таким образом, связь между ними 1:N (один пользователь, много записей о баллах).

Теперь в таблице 'points' я также храню информацию о том, за что пользователь получил очки (логин, клик по баннеру и т.д.). И я хочу вывести список всех пользователей, упорядоченный по SUM(points) И затем по SUM(points WHERE type = x). То есть упорядочить по всем очкам, которые есть у пользователя, а затем по очкам, которые пользователь получил за определенное действие (например, вход в систему).

SQL будет выглядеть так:

SELECT SUM(points.points) AS points_all, SUM(points.points * (points.type = 7)) AS points_login
FROM user
LEFT JOIN points ON user.id = points.user_id
GROUP BY user.id

Вся прелесть этого в SUM(points.points * (points.type = 7)), где внутренняя скобка оценивается либо в 0, либо в 1, таким образом умножая данное значение очков на 0 или 1, в зависимости от того, соответствует ли оно нужному нам типу очков.

3
ответ дан 2 December 2019 в 05:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: