SQL Server запрос, где не будет работать отдельный - выбрать только уникальные записи - и искать уникальность только в одном столбце - PullRequest
0 голосов
/ 09 ноября 2019

У меня есть этот запрос, когда я выбираю записи из таблицы базы данных SQL Server, в которой хранятся все продукты, которые просматривали пользователи нашего сайта (ProductRecentlyViewed таблица).

Я пытаюсь выбратьтолько записи с уникальным rv.productvariantid (я хочу, чтобы он возвращал только один из каждого варианта продукта, который просматривал пользователь).

Я пытался использовать ключевое слово DISTINCT, но мне также нужен DateCreated для orderby, и поскольку он отличается в записях с одинаковым rv.productvariantid, я не могу использовать DISTINCT.

Что я могу сделать вместо этого, чтобы получить 20 новейших уникальных вариантов продукта, которые просматривал пользователь? Вот мой текущий запрос SQL, который выбирает все варианты продукта, которые просматривал пользователь, и, к сожалению, он показывает их более одного раза, если пользователь просматривал их более одного раза.

SELECT TOP 20
    rv.productId,
    p.productNameNO as productName,
    picid,
    picurl,
    rv.productRecentlyViewedId,
    rv.dateCreated,
    rv.lang,
    rv.isUserLoggedIn,
    rv.userId,
    rv.productVariantId
FROM 
    ProductRecentlyViewed rv
INNER JOIN 
    Product AS p ON rv.productid = p.productid
LEFT JOIN 
    (SELECT 
         productid,
         picurl,
         picid,
         ROW_NUMBER() OVER (PARTITION BY productid ORDER BY isfrontpic DESC) rn
     FROM 
         productpic) c ON c.rn = 1
                       AND rv.productId = c.productId
WHERE 
    rv.lang = 'NO'
    AND rv.cookieId = CONVERT(uniqueidentifier, '1f102c74-278b-430e-8129-1261dfc7e2ac')
ORDER BY 
    rv.dateCreated

Ответы [ 2 ]

2 голосов
/ 09 ноября 2019

Сначала выберите все записи в подзапросе, а затем отфильтруйте по rn=1

SELECT TOP 20 q.*
  FROM (SELECT rv.productId,
               p.productNameNO as productName,
               picid,
               picurl,
               rv.productRecentlyViewedId,
               rv.dateCreated,
               rv.lang,
               rv.isUserLoggedIn,
               rv.userId,
               rv.productVariantId,
               pv.productVariantName,
               ROW_NUMBER() OVER(PARTITION BY rv.productid ORDER BY c.isfrontpic DESC) rn 
          FROM ProductRecentlyViewed rv
         INNER JOIN Product as p
            ON rv.productid = p.productid
          LEFT JOIN productpic c
            ON rv.productId = c.productId
          LEFT JOIN ProductVariant pv
            ON productVariantId = rv.productVariantId 
         WHERE rv.lang = 'NO'
           AND rv.cookieId = CONVERT(uniqueidentifier, '123')) q
 WHERE q.rn = 1
 ORDER BY q.dateCreated

Группировка выполняется по PARTITION BY productid, и получите только один productid из каждой группы по rn=1

1 голос
/ 09 ноября 2019

Я бы рекомендовал выполнить фильтрацию следующим образом:

SELECT rv.productId, p.productNameNO as productName,
       pp.picid, pp.picurl,
       rv.productRecentlyViewedId, rv.dateCreated, rv.lang,
       rv.isUserLoggedIn, rv.userId, rv.productVariantId
FROM (SELECT TOP (20) rv.*
      FROM (SELECT rv.*,
                   ROW_NUMBER() OVER (PARTITION BY rv.cookieId, rv.productId ORDER BY rv.dateCreated DESC) as seqnum
            FROM ProductRecentlyViewed rv
            WHERE rv.lang = 'NO' AND
                  rv.cookieId = CONVERT(uniqueidentifier, '1f102c74-278b-430e-8129-1261dfc7e2ac')
           ) rv
      WHERE seqnum = 1
     ) rv JOIN 
    Product p
    ON rv.productid = p.productid OUTER APPLY
    (SELECT TOP (1) pp.*
     FROM productpic pp
     WHERE pp.productid = p.productid
     ORDER BY pp.isfrontpic DESC
    ) pp
ORDER BY rv.dateCreated;

Это дает оптимизатору больше возможностей для ускорения запроса. В частности, он не умножает все строки и затем определяет первое изображение для каждой строки.

Вместо этого он находит 20 строк и затем получает изображение для каждой.

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