MySQL DISTINCT не отфильтровывается

#mysql #sql

#mysql #sql

Вопрос:

У меня следующий SQL-запрос:

 SELECT DISTINCT(tbl_products.product_id), tbl_products.product_title,
            tbl_brands.brand_name, tbl_reviews.review_date_added, 
            NOW() AS time_now
            FROM tbl_products, tbl_reviews, tbl_brands
            WHERE tbl_products.product_id = tbl_reviews.product_id AND
            tbl_products.brand_id = tbl_brands.brand_id
            ORDER BY tbl_reviews.review_date_added DESC
  

Для этого необходимо отфильтровать любые повторяющиеся идентификаторы product_id, к сожалению, выбрав tbl_reviews.review_date_added делает каждую запись уникальной, что означает, что DISTINCT больше не будет работать.

Есть ли какой-либо другой способ выполнить этот запрос, чтобы product_id оставался уникальным?

Я сделал GROUP BY, и проблема в том, что я отображаю tbl_reviews.review_date_added на веб-сайте, и он выбирает самую старую дату. Мне нужна самая последняя дата.

С уважением

Комментарии:

1. Что касается использования max (tbl_reviews.review_date_added) или min (tbl_reviews.review_date_added), вы должны выбрать один tbl_reviews.review_date_added для всех tbl_products.product_id (min и max — это только предложения), иначе это не будет работать (как вы уже заметили).

2. Я прочитал это после того, как я это реализовал. Это действительно работает! =)

Ответ №1:

С приведенным описанием немного сложно быть уверенным, но если review_date_added это единственная проблема, кажется, что вам нужен MAX () этой даты?

Если следующее не помогает, пожалуйста, не могли бы вы привести пример данных, пример выходных данных и описание того, как вы хотите, чтобы выходные данные были созданы?

 SELECT
  tbl_products.product_id,
  tbl_products.product_title,
  tbl_brands.brand_name,
  MAX(tbl_reviews.review_date_added) AS review_date_added,
  NOW() AS time_now
FROM
  tbl_products
INNER JOIN
  tbl_reviews
    ON tbl_products.product_id = tbl_reviews.product_id
INNER JOIN
  tbl_brands
    ON tbl_products.brand_id = tbl_brands.brand_id
GROUP BY
  tbl_products.product_id,
  tbl_products.product_title,
  tbl_brands.brand_name
ORDER BY
  MAX(tbl_reviews.review_date_added) DESC
  

Ответ №2:

Distinct работает для всей строки. Круглые скобки находятся как раз вокруг поля:

 distinct (a), b, c  ===  distinct a, b, c
  

Простым решением является group by . Вы можете использовать min для выбора самой старой даты.

 select  tbl_products.product_id
,       min(tbl_products.product_title)
,       min(tbl_brands.brand_name)
,       min(tbl_reviews.review_date_added)
,       NOW() AS time_now
FROM    tbl_products, tbl_reviews, tbl_brands
WHERE   tbl_products.product_id = tbl_reviews.product_id AND
        tbl_products.brand_id = tbl_brands.brand_id
GROUP BY
        tbl_products.product_id
ORDER BY 
        min(tbl_reviews.review_date_added) DESC
  

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

Ответ №3:

Попробуйте это:

 SELECT pr.product_id, pr.product_title,
       bd.brand_name, 
      (SELECT MAX(rev.review_date_added) FROM tbl_reviews rev
       WHERE pr.product_id = rev.product_id) AS maxdate, 
       NOW() AS time_now
FROM tbl_products pr INNER JOIN tbl_reviews re 
    ON pr.product_id = re.product_id
INNER JOIN tbl_brands bd
    ON pr.brand_id = bd.brand_id
GROUP BY pr.product_id
ORDER BY re.review_date_added DESC
  

или (как предложено @Hogan)

 SELECT pr.product_id, pr.product_title,
       bd.brand_name, md.maxdate
       NOW() AS time_now
FROM tbl_products pr INNER JOIN tbl_reviews re 
    ON pr.product_id = re.product_id
INNER JOIN tbl_brands bd
    ON pr.brand_id = bd.brand_id
INNER JOIN (SELECT product_id, MAX(review_date_added) AS maxdate 
            FROM tbl_reviews rev GROUP BY product_id) md
    ON pr.product_id = md.product_id
GROUP BY pr.product_id
ORDER BY re.review_date_added DESC
  

Комментарии:

1. Быстрее присоединиться к подзапросу с максимальными датами проверки, чем выполнять подзапрос к каждой строке

2. @Hogan: как вы думаете, мой новый запрос правильный? Я действительно не могу это попробовать;)

3. Мне кажется правильным. Я думаю, это будет быстрее, чем принятый ответ. (Также не могу протестировать это прямо сейчас 🙂

Ответ №4:

Я объединил ответ Andomar с некоторыми изменениями, которые вы найдете здесь.

 SELECT tbl_products.product_id, tbl_products.product_title,
                    tbl_products.product_date_added, tbl_brands.brand_name,
                    MAX(tbl_reviews.review_date_added) AS review_date_added, NOW() AS time_now
            FROM tbl_products, tbl_reviews, tbl_brands
            WHERE tbl_products.product_id = tbl_reviews.product_id AND
                    tbl_products.brand_id = tbl_brands.brand_id
            GROUP BY tbl_products.product_id
            ORDER BY MAX(tbl_reviews.review_date_added) DESC
  

Работает прекрасно и показывает самую последнюю дату в tbl_reviews.review_date_added.review_date_added.

С уважением