Внутреннее соединение, кроме одного случая - PullRequest
0 голосов
/ 01 февраля 2020

У меня есть следующая таблица статистики:

id | date | user_id | price | additional_price

Мой запрос выглядит так:

SELECT month, sum(price), sum(additional_price)
FROM statistics s
INNER JOIN users u on s.user_id = u.id
AND u.confirmed = 1
GROUP BY MONTH(date);

Проблема в том, что в этой таблице есть строки, где цена равна 0, но дополнительная_ценка больше 0, где пользователи не подтверждены или больше не существуют. Я хочу посчитать их в выходную сумму. Что-то вроде:

SELECT t.month, sum(t.price), sum(t.additional_price)
FROM (

(SELECT month, sum(price), sum(additional_price)
FROM statistics s
INNER JOIN users u on s.user_id = u.id
WHERE u.confirmed = 1
AND s.price > 0
GROUP BY MONTH(date))
UNION
(SELECT month, sum(price), sum(additional_price)
FROM statistics s
WHERE price = 0
GROUP BY MONTH(date))

) AS t
GROUP BY MONTH(t.date);

Это сработает, вот результат, которого я хочу достичь. Но запрос медленный, большой и не поддерживаемый. Основная проблема, с которой я сталкиваюсь, заключается в том, что я не могу использовать отношения на такой таблице:

$statistics = Statistic::join('users');
$statisticsForZeroPrice = Statistic::forZeroPrice();
$result = DB::query()->fromSub($statistics->union($statisticsForZeroPrice), 't')
 ->with('user') // will not work 
 ->groupBy('t.date')
 ->get();

Есть ли более простое решение этой проблемы?

Ответы [ 4 ]

0 голосов
/ 01 февраля 2020

Ваши 2 объединенных запроса отличаются только условиями условия WHERE. Почему бы не объединить их так:

SELECT MONTH(date) month, SUM(price), SUM(additional_price)
FROM statistics s INNER JOIN users u 
ON s.user_id = u.id
WHERE (u.confirmed = 1 AND s.price > 0) OR (s.price = 0)
GROUP BY MONTH(date);
0 голосов
/ 01 февраля 2020
SELECT month, sum(price), sum(additional_price)
FROM statistics s
LEFT JOIN users u on s.user_id = u.id
WHERE u.confirmed = 1 OR price = 0
GROUP BY MONTH(date);
0 голосов
/ 01 февраля 2020

Как насчет этого?

     SELECT month, sum(price), sum(additional_price) 
       FROM statistics s 
 INNER JOIN users u on s.user_id = u.id 
      WHERE (u.confirmed = 1 AND s.price > 0) OR (u.confirmed = 0 AND s.price = 0) 
   GROUP BY MONTH(date);
0 голосов
/ 01 февраля 2020

Я предполагаю, что вы хотите left join. Из ограниченной информации в вашем вопросе, что-то вроде этого:

SELECT month, sum(price), sum(additional_price)
FROM statistics s LEFT JOIN
     users u
     ON s.user_id = u.id AND u.confirmed = 1
GROUP BY MONTH(date);

Неясно, какая таблица должна быть первой в left join.

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