我有两个表,Product和ProductImages。
产品表有2列:ProductID和Name
ProductImages表有4列:ID,ProductID,ImageName和Primary(bit)。
Product和ProductImages之间的关系是一对多,因此一个产品可以有很多图像,但是对于每个产品,只有一个ProductImage是主要的。
我需要编写一个查询来获取所有带有主图像的产品。如果产品没有主映像,则应获取ProductId的第一条记录。
示例产品表
| 1 | P1 |
| 2 | P2 |
| 3 | P3 |
| 4 | P4 |
示例productImage表
| 1 | 1 | P1-1 | 1
| 2 | 1 | P1-2 | 0
| 3 | 1 | P1-3 | 0
| 4 | 1 | P1-4 | 0
| 5 | 2 | P2-1 | 1
| 6 | 2 | P2-2 | 0
| 7 | 3 | P3-1 | 0
| 8 | 3 | P3-2 | 0
| 9 | 4 | P4-1 | 0
| 10 | 4 | P4-2 | 0
输出表
| 1 | 1 | P1-1 | 1
| 5 | 2 | P2-1 | 1
| 7 | 3 | P3-1 | 0
| 9 | 4 | P4-1 | 0
我希望我澄清了我的问题。请询问是否需要进一步澄清。
答案 0 :(得分:4)
您可以使用row_number
窗口函数执行此操作:
select * from Products p
join (select *, row_number()
over(partition by ProductID order by ID) rn from ProductImages)pi
on p.ProductID = pi.ProductID and pi.rn = 1
我认为主要图片ID
将位于非主要图片ID
之前。
答案 1 :(得分:3)
这有点“快而又脏”,但我的作品是:
SELECT pr.ProductID, pr.Name, prim.ImageName, 1 AS IsPrimary
FROM @product pr
INNER JOIN @productimage prim ON pr.ProductID = prim.ProductID
WHERE prim.[Primary] = 1
UNION ALL
SELECT pr.ProductID, pr.Name, prim.ImageName, 0 AS IsPrimary
FROM @product pr
INNER JOIN
-- Get any image for this Product MIN, MAX,...what you want
(
SELECT ProductID, MIN(ImageName) AS ImageName
FROM @productimage
WHERE [Primary] = 0
GROUP BY ProductID
) prim ON pr.ProductID = prim.ProductID
LEFT JOIN
--Primary Images:
(
SELECT ProductID
FROM @productimage pri
WHERE pri.[Primary] = 1
) primages ON pr.ProductID = primages.ProductID
WHERE primages.ProductID IS NULL --there is no primary image
第一个查询适用于所有拥有主映像的产品,第二个查询适用于那些没有主映像的产品。
答案 2 :(得分:3)
连接数较少,看起来很整洁并完成工作
select a.ProductId, ProductName, ImageName, b.ID as ImageID, b.[Primary] , b.[Primary] as IsPrimary
into a
from tProduct a
inner join tProductImages b on a.ProductID = b.ProductID
where b.[Primary] = 1
;WITH cte AS
(
SELECT a.ProductId, ProductName, ImageName, b.ID as ImageID, b.[Primary] as IsPrimary ,
ROW_NUMBER() OVER (PARTITION BY b.ProductId ORDER BY b.ID) AS rn
from tProduct a
inner join tProductImages b on a.ProductID = b.ProductID
where b.[Primary] = 0 and a.ProductID not in (select ProductId from a)
)
SELECT ImageID, ProductId, ProductName, ImageName, IsPrimary
FROM cte WHERE rn = 1
union
select ImageID, ProductId, ProductName, ImageName, IsPrimary
from a
drop table a
供您参考
修改强>
我只是再次经历它,直到我意识到不需要联合查询,只有下面就足够了
;WITH cte AS
(
SELECT a.ProductId, ProductName, ImageName, b.ID as ImageID, b.[Primary] as IsPrimary ,
ROW_NUMBER() OVER (PARTITION BY b.ProductId ORDER BY b.[Primary] desc, b.ID) AS rn
from tProduct a
inner join tProductImages b on a.ProductID = b.ProductID
)
select * from cte where rn = 1
答案 3 :(得分:1)
决定使用连接和子查询来尝试此解决方案:FIDDLE
SELECT * FROM(
SELECT pi.id as ImageID ,p.id as ProductID,
pi.imagename as ImageName ,pi.primarybit as Primary_
FROM product p
JOIN
(select id, imagename,productid,primarybit
FROM productimage
where primarybit = 1) pi
ON p.id = pi.productid
UNION
SELECT pi.id as ImageID ,p.id as ProductID,
pi.imagename as ImageName ,pi.primarybit as Primary_
FROM product p
JOIN productimage pi
ON p.id = pi.productid
WHERE not p.id in(
select prod.id
from product prod
join productimage prodimg
on prod.id = prodimg.productid
where prodimg.primarybit = 1)
AND pi.id IN (
select min(prodimg.id)
FROM product prod
join productimage prodimg
on prod.id = prodimg.productid
group by prodimg.productid
)) magictable
ORDER BY ImageID
答案 4 :(得分:1)
简单加入交叉申请应该这样做
Select p.*, i.*
from Product p
inner join ProductImage i on p.ProductId = i.ProductId
cross apply(Select
ProductId,
MinProId = MIN(ProductImageId),
PrimaryProductId = MIN(case when IsPrimary=1 then ProductImageId else null end)
from ProductImage i
where i.ProductId = p.ProductId
group by i.ProductId )s
where i.ProductImageId= isnull(s.PrimaryProductId, s.MinProId)