SQL Server:如何为分页购物篮列表关联单篇文章首图?
解决方案:为购物篮文章关联单张图片并结合分页
针对你遇到的临时表关联时子查询无法引用外层字段的问题,这里提供三种可行的实现方案,同时结合DENSE_RANK完成分页逻辑:
方案1:使用OUTER APPLY(推荐)
OUTER APPLY允许右侧子查询直接引用左侧表(#produit)的字段,完美适配你的场景,且逻辑清晰,支持保留无图片的文章记录:
SELECT p.*, pic.url AS article_image FROM #produit p OUTER APPLY ( -- 取当前文章的一张图片,可按需添加排序规则(比如最新上传) SELECT TOP 1 url FROM #pictures pic WHERE pic.pk_article = p.pk_article ORDER BY pic.create_date DESC ) pic
结合分页的写法
如果要加入DENSE_RANK分页逻辑,只需套一层CTE即可:
WITH PagedBasket AS ( SELECT p.*, pic.url AS article_image, -- 按购物篮添加时间排序生成排名,用于分页 DENSE_RANK() OVER (ORDER BY p.add_date DESC) AS page_rank FROM #produit p OUTER APPLY ( SELECT TOP 1 url FROM #pictures pic WHERE pic.pk_article = p.pk_article ORDER BY pic.create_date DESC ) pic ) -- 取第1页,每页10条数据 SELECT * FROM PagedBasket WHERE page_rank BETWEEN 1 AND 10;
方案2:用窗口函数预标记主图后关联
先通过窗口函数给每个文章的图片分组排序,标记出要取的单张图片,再与购物篮表关联:
WITH RankedPictures AS ( SELECT pk_article, url, -- 按图片上传时间倒序,给每个文章的图片排名 ROW_NUMBER() OVER (PARTITION BY pk_article ORDER BY create_date DESC) AS pic_seq FROM #pictures ) SELECT p.*, rp.url AS article_image FROM #produit p LEFT JOIN RankedPictures rp ON p.pk_article = rp.pk_article AND rp.pic_seq = 1; -- 只取每个文章的第一张图片
结合分页的写法
同样套入CTE实现分页:
WITH RankedPictures AS ( SELECT pk_article, url, ROW_NUMBER() OVER (PARTITION BY pk_article ORDER BY create_date DESC) AS pic_seq FROM #pictures ), PagedBasket AS ( SELECT p.*, rp.url AS article_image, DENSE_RANK() OVER (ORDER BY p.add_date DESC) AS page_rank FROM #produit p LEFT JOIN RankedPictures rp ON p.pk_article = rp.pk_article AND rp.pic_seq = 1 ) SELECT * FROM PagedBasket WHERE page_rank BETWEEN 1 AND 10;
方案3:SELECT列表中使用关联子查询
如果偏好简洁的写法,可直接在SELECT列中嵌入关联子查询,直接引用外层表的pk_article:
SELECT p.*, -- 取当前文章的一张图片 (SELECT TOP 1 url FROM #pictures pic WHERE pic.pk_article = p.pk_article ORDER BY create_date DESC) AS article_image FROM #produit p
结合分页的写法
WITH PagedBasket AS ( SELECT p.*, (SELECT TOP 1 url FROM #pictures pic WHERE pic.pk_article = p.pk_article ORDER BY create_date DESC) AS article_image, DENSE_RANK() OVER (ORDER BY p.add_date DESC) AS page_rank FROM #produit p ) SELECT * FROM PagedBasket WHERE page_rank BETWEEN 1 AND 10;
内容的提问来源于stack exchange,提问作者Lucas Weibel
相关产品推荐
相关产品推荐

