Более быстрая альтернатива CROSS JOIN - PostgreSQL - PullRequest
0 голосов
/ 14 января 2010

Я пытаюсь объединить две таблицы: клиенты и товары, чтобы затем создать отчет о продажах по клиентам. У меня 2000 клиентов и 2000 предметов.

SELECT customer_name FROM customers; --Takes 100ms

SELECT item_number FROM items; --Takes 50ms

SELECT customer_name, item_number FROM customers CROSS JOIN items; Takes 200000ms

Я знаю, что это 4 миллиона строк, но можно ли заставить его работать быстрее? Я хочу в конечном итоге присоединиться к этому с таблицей продаж, как это:

SELECT customer_name, item_number, sales_total FROM customers CROSS JOIN items LEFT JOIN sales ON (customer.customer_name = sales.customer_name, item.item_number=sales.item_number);

Очевидно, что в таблице продаж будут указаны не все клиенты или не все товары, поэтому цель состоит в том, чтобы получить отчет, в котором будут показаны все клиенты и все товары, а также то, что было продано и не продано.

Я использую PostgreSQL 8.4

Ответы [ 5 ]

4 голосов
/ 14 января 2010

Чтобы ответить на ваш вопрос: Нет, вы не можете сделать перекрестное соединение быстрее, чем это - если бы вы могли, то именно так и был бы реализован CROSS JOIN.

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

1 голос
/ 19 января 2010

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

  1. Отчет: подсчет всех покупок клиентом / товаром (очевидно).
  2. Отчет: список всех предметов, не купленных клиентом.
  3. Отчет: сводка отчета № 2 (количество предметов) с целью определения приоритетов клиентов.
  4. Отчет: список всех клиентов, которые не купили товар по пунктам.
  5. Отчет: сводка отчета № 3 (количество клиентов) с целью определения как самых популярных, так и непопулярных элементов для дальнейших действий.
  6. Отчет. Список всех клиентов, которые приобрели товар в прошлом, но не приобрели его в течение отчетного периода. Этот отчет актуален только тогда, когда в таблице продаж указана дата, и ожидается, что клиенты будут постоянными покупателями (то есть одноразовыми виджетами). Не подойдет для таких вещей, как контракты на обслуживание.

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

0 голосов
/ 17 февраля 2014

Возможно, вы хотите что-то подобное?

select c.customer_name, i.item_number, count( s.customer_name ) as total_sales
from customers c full join sales s on s.customer_name = c.customer_name
full join items i on i.item_number = s.item_number
group by c.customer_name, i.item_number
0 голосов
/ 14 января 2010

Если вы хотите просмотреть все предметы для данного клиента (даже если у покупателя нет предметов), я бы лучше попробовал

SELECT c.customer_name, i.item_number, s.sales_total
FROM customers c LEFT JOIN 
    sales s ON c.customer_name = s.customer_name LEFT OIN
    items i on i.item_number=s.item_number

Это должно дать вам список всех клиентов и всех товаров, объединенных продажами.

0 голосов
/ 14 января 2010

Я не могу себе представить, что для этого будет стороннее решение, программисты PostgreSQL лучше знают свою систему и будут сильно оптимизировать ее.

...