Как правильно работать с базой где в одной таблице 110 000 записей.

Webage

Новичок
Доброго вечера. Имеется следующая задача. В таблице 110000 записей с информацией о компаниях. Мне необходимо понять сколько в определенный интервал времени появилось новых компаний. Ход действий которые есть сейчас
1) выбираю список компаний за определенный интервал, допустим месяц с помощью distinct и загоняю все это дело в массив.
2) прохожу по массиву и на каждую компанию которая есть в массиве делаю запрос в базу только за период до того интервала который был в 1 пункте.
Все замечательно работает, но есть проблема если 1 пункт выполняется за 1 секунду то второй может выполняться от 20 до 50 секунд. Подскажите может есть другой подход. Оговорюсь, что все это выполняется на localhost и по ресурсам я не ограничен.
 

Webage

Новичок
А каким образом мне сделать все через 1 запрос? Мне же нужно узнать не было ли то этого упоминания в записях о них.
 

Gas

может по одной?
схематично как-то так

select company_id, (select 1 from table where company_id=t.company_id and date < [date1] limit 1) as isExists
from table as t
where date between [date1] and [date2]
group by company_id
having isExists is null;
 

Webage

Новичок
Что то я совсем не отдупляю. У меня сейчас есть следующее:
PHP:
$get_all_customers = $conn->Execute("SELECT DISTINCT `company_identifier`, `manager`, `company_name` FROM `all_sales` WHERE `manager`!=\"Ларин\" AND `manager`!=\"\" AND `sale_date_ut`>=\"1380585600\" AND `sale_date_ut`<=\"1383264000\"");
if ($get_all_customers && $get_all_customers->RecordCount() > 0) {
      while (!$get_all_customers->EOF) {
      $get_new_customers = $conn->Execute("SELECT `company_identifier` FROM `all_sales` WHERE `company_identifier`=\"".$get_all_customers->fields['company_identifier']."\" AND `sale_date_ut`<\"1380585600\"");
      if ($get_new_customers && $get_new_customers->RecordCount() > 0) {
    }
    if ($get_new_customers && $get_new_customers->RecordCount() == 0) {
      echo "".$get_all_customers->fields['company_identifier']." ".$get_all_customers->fields['company_name']." ".$get_all_customers->fields['manager']."<br>";
  }
      $get_all_customers->MoveNext();
  }
}
Как это заставить работать быстрее, подзапросы я вообще не понимаю как работают.
 

StVolodymyr

Новичок
Насколько я вижу вы получаете данные из таблицы all_sales в которой я догадываюсь находяться все продажи компаний, потому у вас так много даных. Как вариант можно попробовать сделать две temporary tables одна с компаниями до указаного периода (temporary_c1), а вторая за указанный период (temporary_c2). А потом через запрос
Код:
SELECT * FRON temporary_c2
LEFT JOIN  temporary_c1 using(company_identifier)
WHERE temporary_c1.company_identifier is null
Таким образом вы будете делать LEFT JOIN таблиц с меньшим количеством данных
 

Webage

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

StVolodymyr

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

Код:
CREATE TEMPORARY TABLE IF NOT EXISTS temporary_c2 AS(
SELECT DISTINCT `company_identifier` WHERE  `sale_date_ut`>=[start_period] AND `sale_date_ut`<=[end_period]
);

CREATE TEMPORARY TABLE IF NOT EXISTS temporary_c1 AS(
SELECT DISTINCT `company_identifier` WHERE  `sale_date_ut`<[start_period]
);

SELECT * FRON temporary_c2
LEFT JOIN temporary_c1 using(company_identifier)
WHERE temporary_c1.company_identifier is null'
 

Gas

может по одной?
так пробовал ?

ну или можно вариант с fullscan'ом, всё равно не ясно что будет быстрее пачка подзапросов или один фулскан

PHP:
SELECT company_identifier, SUM(sale_date_ut < [date1]) AS existsBefore,
       SUM(sale_date_ut >= [date1] AND sale_date_ut <= [date2]) AS salesInPeriod
FROM all_sales
GROUP BY company_identifier
HAVING existsBefore = 0 AND salesInPeriod > 0
 
Последнее редактирование:

Тугай

Новичок
Gas уже дал ответ.
Еще вариант:
Код:
SELECT DISTINCT `company_identifier`, `manager`, `company_name`
FROM `all_sales`
WHERE `manager`!=\"Ларин\" AND `manager`!=\"\"
    AND `sale_date_ut`>=\"1380585600\" AND `sale_date_ut`<=\"1383264000\""
    AND not exists(
        SELECT `company_identifier`
        FROM `all_sales`
        WHERE `company_identifier`=\"".$get_all_customers->fields['company_identifier']."\"
            AND `sale_date_ut`<\"1380585600\"
        )
Логика та же просто делается все средствами mysql. (выбрать компании за период которые не встречаются раньше).
 

keltanas

marty cats
Может стоило при добавлении новой компании указывать created_at в виде datetime?
 

Webage

Новичок
Может стоило при добавлении новой компании указывать created_at в виде datetime?
А вот эта идея хороша, выгружаю таблицу, выбираю уникальные компании и перекидываю их в новую базу с указанием первой операции и уже из второй таблицы подтягиваю данные за период. Единственное, что смущает это сумма продаж по компаниям. Получается для получения суммы продаж по каждой компании - необходимо опять тормошить таблицу из 110000 записей.
 

keltanas

marty cats
Сделай индекс на all_sales.company_identifier
И тогда можно даже left join обойтись и группировкой по company_identifier
 
Сверху