Соединить несколько Select в один

210
03 ноября 2018, 21:30

У меня есть следующий код:

function get($min, $max)
{
    // Хосты и хиты
    $query = $this->db->query('
        SELECT COUNT(DISTINCT ip2long) AS hosts, COUNT(*) AS hits, `date` FROM tracking
        WHERE user_id = "' . $this->user_id . '" ' . ($this->sub_id != 0 ? 'AND sub_id = "' . $this->db->escape($this->sub_id) . '" ' : '') . ($this->offer_id != 0 ? 'AND offer_id = "' . $this->db->escape($this->offer_id) . '" ' : '') . 'AND time BETWEEN "' . strtotime($this->days_array[$min] . ' 00:00') . '" AND "' . strtotime($this->days_array[$max] . ' 23:59') . '"
        GROUP BY `date` ASC
    ');
    foreach ($query->result_array() as $k) {
        $this->data[$k['date']]['tracking']['hosts'] = $k['hosts'];
        $this->data[$k['date']]['tracking']['hits'] = $k['hits'];
    }
    // Конверсии
    $query = $this->db->query('
        SELECT COUNT(*) AS count, SUM(summa) AS summa, `date` FROM conversions
        WHERE user_id = "' . $this->user_id . '" ' . ($this->sub_id != 0 ? 'AND sub_id = "' . $this->db->escape($this->sub_id) . '" ' : '') . ($this->offer_id != 0 ? 'AND offer_id = "' . $this->db->escape($this->offer_id) . '" ' : '') . 'AND status = "1" AND time BETWEEN "' . strtotime($this->days_array[$min] . ' 00:00') . '" AND "' . strtotime($this->days_array[$max] . ' 23:59') . '"
        GROUP BY `date` ASC
    ');
    foreach ($query->result_array() as $k) {
        $this->data[$k['date']]['conversions']['count'] = $k['count'];
        $this->data[$k['date']]['conversions']['summa'] = $k['summa'];
    }
    // Регистрации
    $query = $this->db->query('
        SELECT COUNT(*) AS count, SUM(summa) AS summa, `date` FROM event_register
        WHERE user_id = "' . $this->user_id . '" ' . ($this->sub_id != 0 ? 'AND sub_id = "' . $this->db->escape($this->sub_id) . '" ' : '') . ($this->offer_id != 0 ? 'AND offer_id = "' . $this->db->escape($this->offer_id) . '" ' : '') . 'AND status = "1" AND time BETWEEN "' . strtotime($this->days_array[$min] . ' 00:00') . '" AND "' . strtotime($this->days_array[$max] . ' 23:59') . '"
        GROUP BY `date` ASC
    ');
    foreach ($query->result_array() as $k) {
        $this->data[$k['date']]['register']['count'] = $k['count'];
        $this->data[$k['date']]['register']['summa'] = $k['summa'];
    }
    // Покупки
    $query = $this->db->query('
        SELECT COUNT(*) AS count, SUM(summa) AS summa, `date` FROM event_buy
        WHERE user_id = "' . $this->user_id . '" ' . ($this->sub_id != 0 ? 'AND sub_id = "' . $this->db->escape($this->sub_id) . '" ' : '') . ($this->offer_id != 0 ? 'AND offer_id = "' . $this->db->escape($this->offer_id) . '" ' : '') . 'AND status = "1" AND time BETWEEN "' . strtotime($this->days_array[$min] . ' 00:00') . '" AND "' . strtotime($this->days_array[$max] . ' 23:59') . '"
        GROUP BY `date` ASC
    ');
    foreach ($query->result_array() as $k) {
        $this->data[$k['date']]['buy']['count'] = $k['count'];
        $this->data[$k['date']]['buy']['summa'] = $k['summa'];
    }
    // Заработок с рефералов
    $query = $this->db->query('
        SELECT SUM(summa) AS summa, `date` FROM referals
        WHERE user_id = "' . $this->user_id . '" AND time BETWEEN "' . strtotime($this->days_array[$min] . ' 00:00') . '" AND "' . strtotime($this->days_array[$max] . ' 23:59') . '"
        GROUP BY `date` ASC
    ');
    foreach ($query->result_array() as $k) {
        $this->data[$k['date']]['referals']['summa'] = $k['summa'];
    }
    $return = array();
    foreach ($this->data as $key => $k) {
        if (strtotime($key) >= strtotime($this->days_array[$min]) && strtotime($key) <= strtotime($this->days_array[$max])) {
            $return[$key] = $this->data[$key];
            $return[$key]['date'] = $key;
            // Трекинг
            $return[$key]['tracking']['hosts'] = (isset($return[$key]['tracking']['hosts']) ? $return[$key]['tracking']['hosts'] : 0);
            $return[$key]['tracking']['hits'] = (isset($return[$key]['tracking']['hits']) ? $return[$key]['tracking']['hits'] : 0);
            // Конверсии
            $return[$key]['conversions']['count'] = (isset($return[$key]['conversions']['count']) ? $return[$key]['conversions']['count'] : 0);
            $return[$key]['conversions']['summa'] = (isset($return[$key]['conversions']['summa']) ? $return[$key]['conversions']['summa'] : 0);
            // Регистрации
            $return[$key]['register']['count'] = (isset($return[$key]['register']['count']) ? $return[$key]['register']['count'] : 0);
            $return[$key]['register']['summa'] = (isset($return[$key]['register']['summa']) ? $return[$key]['register']['summa'] : 0);
            // Покупки
            $return[$key]['buy']['count'] = (isset($return[$key]['buy']['count']) ? $return[$key]['buy']['count'] : 0);
            $return[$key]['buy']['summa'] = (isset($return[$key]['buy']['summa']) ? $return[$key]['buy']['summa'] : 0);
            // Рефералы
            $return[$key]['referals']['summa'] = (isset($return[$key]['referals']['summa']) ? round($return[$key]['referals']['summa'], 2) : 0);
            // Менеджеры
            $return[$key]['managers']['summa'] = (isset($return[$key]['managers']['summa']) ? round($return[$key]['managers']['summa'], 2) : 0);
            // Общая сумма
            $return[$key]['summa'] = round($return[$key]['conversions']['summa'] + $return[$key]['register']['summa'] + $return[$key]['buy']['summa'] + $return[$key]['referals']['summa'] + $return[$key]['managers']['summa'], 2);
            // CTR
            $return[$key]['ctr'] = ((isset($return[$key]['buy']['count']) && isset($return[$key]['conversions']['count']) && $return[$key]['buy']['count'] > 0 && $return[$key]['conversions']['count'] > 0) ? round(($return[$key]['buy']['count'] / $return[$key]['conversions']['count']) * 100) : 0);
            // CR (Конверт)
            $return[$key]['cr'] = ((isset($return[$key]['tracking']['hosts']) && isset($return[$key]['conversions']['count']) && $return[$key]['tracking']['hosts'] > 0 && $return[$key]['conversions']['count'] > 0) ? round(($return[$key]['conversions']['count'] / $return[$key]['tracking']['hosts']) * 100) : 0);
            // Всего трекинг
            $this->total['tracking']['hosts'] += $return[$key]['tracking']['hosts'];
            $this->total['tracking']['hits'] += $return[$key]['tracking']['hits'];
            //Конверсии всего
            $this->total['conversions']['count'] += $return[$key]['conversions']['count'];
            // Регистрации всего
            $this->total['register']['count'] += $return[$key]['register']['count'];
            // Покупки всего
            $this->total['buy']['count'] += $return[$key]['buy']['count'];
            // Рефералы всего
            $this->total['referals']['summa'] += $return[$key]['referals']['summa'];
            // Общая сумма
            $this->total['summa'] += ($return[$key]['summa']);
        }
    }
    krsort($return);
    return $return;
}

Как видите, не самый оптимальный способ получения данных. Я бы хотел объединить эти селекты в один. При этом, я подумал о том, что нужно использовать FULL JOIN. Вот почему. Мне нужна таблица следующего вида

Количество строк в этой таблице будет равно количеству строк максимально большой выборки одного из селектов. Для примера возьму первый селект. Вот запрос:

SELECT  user_id, COUNT(DISTINCT ip2long) AS hosts, COUNT(*) AS hits, 
date FROM tracking
WHERE user_id = 8 AND time BETWEEN '1533884400' AND '1534402800'
GROUP BY tracking.date;

Вот результат:

Но мне хотелось бы что то типа такого:

Для этого я написал вот такой запрос:

SELECT * FROM
(SELECT  MIN(time) as min_time, user_id, COUNT(DISTINCT ip2long) AS 
  hosts, COUNT(*) AS hits, date FROM tracking
WHERE user_id = 8 AND time BETWEEN '1533884400' AND '1534402800'
GROUP BY tracking.date) as track
LEFT JOIN (
SELECT time, user_id, COUNT(*) AS count, SUM(summa) AS summa, date 
FROM conversions
WHERE user_id = 8 AND time BETWEEN '1533884400' AND '1534402800'
GROUP BY date, time) conv ON conv.user_id = track.user_id AND 
  track.min_time = conv.time
UNION ALL
SELECT * FROM
(SELECT MIN(time) as min_time, user_id, COUNT(DISTINCT ip2long) AS 
  hosts, COUNT(*) AS hits, date FROM tracking
WHERE user_id = 8 AND time BETWEEN '1533884400' AND '1534402800'
GROUP BY tracking.date) as track
RIGHT JOIN (
SELECT MIN(time) as min_time, user_id, COUNT(*) AS count, SUM(summa) 
  AS summa, date FROM conversions
WHERE user_id = 8 AND time BETWEEN '1533884400' AND '1534402800'
GROUP BY date, time) conv ON conv.user_id = track.user_id AND 
  track.min_time = conv.min_time
WHERE track.user_id is NULL  OR  track.user_id is NULL AND 
  track.min_time is NULL ;

Тут я пытаюсь реализовать full join (так как его нет в mysql). Вопрос следующий, это оптимальный способ или есть какой то способ лучше?

READ ALSO
Laravel 5. wherehas с полным соотвествием many to many

Laravel 5. wherehas с полным соотвествием many to many

Как реализовать получение выборке, где связанные параметры проверяются не по наличию хотя-бы одного, а если только есть все указанныеНапример:

148
Как получить динамическую цену в php

Как получить динамическую цену в php

Делаю форму онлайн бронирования отелей и столкнулся с проблемой: у меня добавлена функция автоматического подсчета стоимости в зависимости...

146
Перезапускается php скрипт каждые 40 секунд

Перезапускается php скрипт каждые 40 секунд

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

232
NETELLER API получить баланс

NETELLER API получить баланс

Я изучаю API NETELLER PHP и не могу нигде найти примера каким образом можно получить баланс моего аккаунта, неужели это невозможно ?

159