MySQL эффективность запросов, извлекая отдельные записи из похожих групп

0

Я btc таблицу, в которой показаны экземпляры, где более 1 записи содержат один и тот же btc, но для разных btc customer_names, также показывающий мне самый низкий экземпляр cost для каждого клиента.

Этот запрос работает, но он очень неэффективен, и для работы на столе в 80 000 строк требуется минута, поэтому я чувствую, что должен делать что-то неправильно.

select btc,customer_name,min(cost) from table where table.btc in
 (select btc from table group by 1 having count(distinct customer_name) > 1) 
 group by 1,2

Это выводит таблицу следующим образом:

+---------+---------------+---------+
|   btc   | customer_name |  cost   |
+---------+---------------+---------+
| asd32   | Sony          | 1.45863 |
| asd32   | Nintendo      | 1.84839 |
| bf33940 | Sony          | 2.49188 |
| bf33940 | Nintendo      | 2.49188 |
| a43c3f  | Sony          | 2.84142 |
| a43c3f  | Nintendo      | 2.45    |
| a43c3f  | Sega          | 2.689   |
+---------+---------------+---------+

Я хотел бы сделать этот шаг дальше и НЕ включать какой-либо результат, где cost обоих полей customer_name одинакова (так что удаление btc bf33940 из приведенной выше таблицы, поскольку Sony и Nintendo имеют одинаковую стоимость)

Я также хотел бы знать, есть ли более эффективный способ делать то, что я делаю.

Структура таблицы

+------------------+--------------+------+-----+---------+
|      field       |     type     | null | key | default |
+------------------+--------------+------+-----+---------+
| btc              | varchar(100) | NO   | MUL | NULL    |
| mpn              | varchar(100) | YES  |     | NULL    |
| supplier         | varchar(100) | YES  |     | NULL    |
| invoice          | varchar(100) | YES  |     | NULL    |
| invoice_date     | datetime     | YES  |     | NULL    |
| qtr              | varchar(5)   | YES  |     | NULL    |
| qty              | double(10,0) | YES  |     | NULL    |
| resale           | double(15,5) | YES  |     | NULL    |
| ext_resale       | double(15,5) | YES  |     | NULL    |
| cost             | double(15,5) | YES  |     | NULL    |
| ext_cost         | double(15,5) | YES  |     | NULL    |
| gpp              | double(15,5) | YES  |     | NULL    |
| project          | varchar(100) | YES  |     | NULL    |
| team             | double(15,5) | YES  |     | NULL    |
| build_type       | varchar(50)  | YES  |     | NULL    |
| customer_name    | varchar(100) | YES  |     | NULL    |
| customer_address | varchar(100) | YES  |     | NULL    |
| customer_type    | varchar(100) | YES  |     | NULL    |
| customer_group   | varchar(100) | YES  |     | NULL    |
| sps              | varchar(100) | YES  |     | NULL    |
| fps              | varchar(100) | YES  |     | NULL    |
| gps              | varchar(100) | YES  |     | NULL    |
| hps              | varchar(100) | YES  |     | NULL    |
+------------------+--------------+------+-----+---------+

образец файла CSV здесь: https://ufile.io/os0as

  • 1
    Можете ли вы дать структуру таблицы? И некоторые данные.
Теги:

1 ответ

1
Лучший ответ

Вы могли бы попытаться заменить ваш, where...in результате join хотя трудно сказать, насколько эффективнее это будет без тестирования.

Что-то вроде этого:

select t1.btc, customer_name, min(cost)
from xxx t1
join (
  select btc
  from xxx
  group by btc
  having count(*) > 1
) t2 on t1.btc = t2.btc
group by t1.btc, t1.customer_name

Для вашего второго вопроса вы можете дополнительно группировать по btc и стоимости для удаления дубликатов:

select t3.btc, group_concat(t3.customer_name), min_cost
from (
   select t1.btc, t1.customer_name, min(cost) as min_cost
   from xxx t1
   join (
      select btc
      from xxx
      group by btc
      having count(distinct customer_name) > 1
   ) t2 on t1.btc = t2.btc
) t3
group by t1.btc, t1.cost

Снова трудно сказать, будет ли это работать без тестирования, но, надеюсь, вы получите эту идею.

Чтобы ускорить работу, я сделал бы отдельную таблицу с каждым btc и счетчиком количества клиентов, поэтому вам не нужно создавать временную таблицу с count()> 1.

  • 0
    Спасибо! Я возвращаю синтаксическую ошибку для этих операторов SQL на ) t2 on t2 on t1.btc = t2.btc
  • 0
    @BrianPowell да, очевидно, это опечатка, есть "на t2" дополнительно :) Я отредактировал свой ответ. Как я уже сказал, это не проверено.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню