1 votes

Sélection aléatoire des 3 meilleures annonces par magasin pour une série de magasins publicitaires actifs

J'essaie d'afficher une liste de magasins avec chacun 3 articles aléatoires de leur magasin, s'ils ont 3 annonces ou plus, et qui font de la publicité active. J'ai 3 tables : une pour les boutiques - "Shops", une pour les annonces - "Listings" et une qui suit les annonceurs actifs - "AdShops".

En utilisant l'instruction ci-dessous, les listes renvoyées sont aléatoires, mais je n'obtiens pas exactement 3 listes (lignes) par magasin.

SELECT AdShops.ID, Shops.url, Shops.image_url, Shops.user_name AS shop_name,
       Shops.title, L.listing_id AS listing_id, L.title AS listing_title,
       L.price as price, L.image_url AS listing_image_url, L.url AS listing_url
FROM   AdShops INNER JOIN
       Shops ON AdShops.user_id = Shops.user_id INNER JOIN
       Listings AS L ON Shops.user_id = L.user_id
WHERE  (Shops.is_vacation = 0 AND Shops.listing_count > 2 AND 
        L.listing_id IN
            (SELECT TOP 3 L2.listing_id
             FROM   Listings AS L2
             WHERE  L2.listing_id IN 
                 (SELECT TOP 100 PERCENT L3.listing_id
                  FROM   Listings AS L3
                  WHERE  (L3.user_id = L.user_id)
                 )
             ORDER BY NEWID()
            )
       )
ORDER BY Shops.shop_name

Je suis perplexe. Quelqu'un a-t-il une idée sur la façon de résoudre ce problème ?

La solution idéale serait un enregistrement par magasin avec les 3 listes (et les données associées) en colonnes et non en lignes - est-ce possible ?

1voto

Lieven Keersmaekers Points 32396

Si je ne me trompe pas, la requête ci-dessous devrait vous donner tous les user_id ayant au moins 3 listing_id aléatoires.

SELECT  user_id
        , listing_id
FROM    (
          SELECT  l.user_id 
                  , l.listing_id
                  , RowNumber = ROW_NUMBER() OVER (PARTITION BY l.user_id ORDER BY NEWID())
          FROM    Listings l
                  INNER JOIN (
                    SELECT  user_id
                    FROM    Listings
                    GROUP BY
                            user_id
                    HAVING  COUNT(*) >= 3
                  ) cnt ON cnt.user_id = l.user_id  
        ) l 
WHERE   l.RowNumber <= 3

1voto

GraGra33 Points 151

Merci à Lieven pour la clé du problème. La solution complète est la suivante :

SELECT AdShops.ID, Shops.url, Shops.image_url, 
       Shops.user_name AS shop_name, Shops.title, L.listing_id AS listing_id, 
       L.title AS listing_title, L.price as price,
       L.image_url AS listing_image_url, L.url AS listing_url
FROM   AdShops INNER JOIN
       Shops ON AdShops.user_id = Shops.user_id INNER JOIN
       Listings AS L ON Shops.user_id = L.user_id
WHERE  (Shops.is_vacation = 0 AND Shops.listing_count > 2 AND 
        L.listing_id IN
            (SELECT listing_id
             FROM    
                 (SELECT l2.user_id , l2.listing_id, RowNumber = ROW_NUMBER() 
                  OVER   (PARTITION BY l2.user_id ORDER BY NEWID())
                  FROM   Listings l2 INNER JOIN
                      (SELECT   user_id
                       FROM     Listings
                       GROUP BY user_id
                       HAVING   COUNT(*) >= 3
                      ) cnt ON cnt.user_id = l2.user_id  
                 ) l2 
             WHERE l2.RowNumber <= 3 and L2.user_id = L.user_id
            )
       )
ORDER BY Shops.shop_name

Bonne lecture !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X