Как условно присоединиться и получить данные из таблицы объединения? - PullRequest
0 голосов
/ 07 января 2019

У меня есть две таблицы, Product и ProductNewsletter. Продукт может иметь много значений product_newsletters, поэтому в рельсах это отношение has_many на стороне продуктов и belongs_to на стороне product_newsletter с product_id. Таблицы выглядят так:

products
id title... etc

product_newsletters
id product_id date

Я хотел бы получить продукты, у которых есть product_newsletter в диапазоне дат, а также выбрать дату из найденного product_newsletter в запросе. Таким образом, если у продукта есть два product_newsletter с датами 11-03-2018, 20-03-2018 и 04-04-2018, запросы с датами между 01-03-2018 и 30-01-03-2018 должны отобразить этот продукт дважды один раз с 11-03-2018, а другой с 20-03-2018. Сначала я попытался это объединить с подзапросом:

SELECT *
     , news.date AS newsletter_date 
  FROM products 
  JOIN 
     ( SELECT newsletter_products.* 
         FROM newsletter_products 
        WHERE newsletters.date BETWEEN '2018-01-03' AND '2018-01-20'
     ) news 
    ON  products.id = news.product_id

Но это объединение приводит к продукту с идентификатором, который совпадает с теми информационными бюллетенями в подзапросе, а не в product_id, как я ожидал из подзапроса. Я использую рубин на рельсах и Mysql. Моя идея состоит в том, чтобы использовать результаты этого запроса, чтобы просто сделать ruby ​​products.group_by(&:newsletter_date) и получить хороший хеш с датами в качестве ключей и продуктами в качестве значений, без дополнительных запросов или фильтрации для каждой даты, что является моей текущей реализацией.

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Вы должны написать запрос так:

SELECT p.*, n.date AS newsletter_date
FROM products p INNER JOIN 
     newsletter_products np
     ON p.id = n.product_id
WHERE np.date BETWEEN '2018-01-03' AND '2018-01-20';

Примечания:

  • Не используйте select *. Вы получите дату рассылки дважды.
  • Подзапрос не нужен и может помешать оптимизации.
  • Используйте псевдонимы таблиц, чтобы легче было писать и читать запрос.
  • Мне не нравится between с датами, но это логика, которую вы делаете. Безопасно, когда date не имеет временной составляющей.
0 голосов
/ 07 января 2019

Следующий даст вам ожидаемый результат,

Product.joins(:product_newsletters).where(product_newsletters: { date: ['19-01-2013'.to_datetime..'19-02-2013'.to_datetime] })

Если 2 объекта product_newsletters попадают в диапазон дат и оба имеют одинаковый product_id, все равно для указанного выше запроса вы получите 2 counts для одного и того же идентификатора продукта.

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