加入并获得每个id的单行

时间:2014-02-10 05:49:31

标签: sql sql-server sql-server-2008

我的问题很简单。我有两个表,一个product表和一个image表,每个产品有多个图像。

Product

+-----------+-------------+
| productId | ProductName |
+-----------+-------------+
|         1 | product1    |
|         2 | product2    |
+-----------+-------------+

Image表:

+---------+-----------+-----------+--+
| imageId | imagePath | productId |  |
+---------+-----------+-----------+--+
|       1 | img1      |         1 |  |
|       2 | img2      |         1 |  |
|       3 | img3      |         2 |  |
|       4 | img4      |         2 |  |
+---------+-----------+-----------+--+

我想获得如下输出

+-----------+-------------+---------+-----------+--+
| productId | productName | imageId | imagePath |  |
+-----------+-------------+---------+-----------+--+
|         1 | product1    |       1 | img1      |  |
|         2 | product2    |       3 | img3      |  |
+-----------+-------------+---------+-----------+--+

即。应该只有一个图像对应每个产品。

目前我已经用光标完成了这项工作,但作为优化,我必须找到另一种方法。我正在使用SQL Server 2008。

提前致谢...

5 个答案:

答案 0 :(得分:1)

您可以通过加入过滤的imageId,为每个productId仅选择一个imageId(最小值):

SELECT p.ProductId, ProductName, i.imageId, imagePath
FROM product p
    INNER JOIN Image i 
        ON i.ProductId = p.ProductId
    INNER JOIN
        (SELECT MIN(imageId) As imageId, ProductId
         FROM image
         GROUP BY ProductId
         ) o 
         ON o.imageId = i.imageId

或使用WHERE子句过滤imageId:

SELECT p.ProductId, ProductName, imageId, imagePath
FROM product p
    INNER JOIN Image i 
        ON i.ProductId = p.ProductId
WHERE imageId IN
    (SELECT MIN(imageId) As imageId
     FROM image
     GROUP BY ProductId
     )

SQLFiddle Demo

答案 1 :(得分:0)

在SQL Server 2005中,我使用嵌套查询执行此操作,该查询找到按productId分组的最小或最大imageId。也许2008年有更好的方式。

select 
  productId, 
  productName,
  minImageId,
  imagePath
from
  product inner join (
    select
      productId,
      min(imageId) as minImageId
    from
      Image
    group by 
      productId) minImages
  on
    product.id = minImages.productId

答案 2 :(得分:0)

您可以使用CTE执行此操作,例如

With FirstImage as(
  Select min(imageid) imageid,
         productid
  From Image
  Group by
  productid)

Select p.productid,
       p.productname,
       i.imageid,
       i.imagepath
from FirstImage fi
inner join image i on i.imageid=fi.imageid
inner join product p on p.productId=i.productid

<强> SQLFiddle

答案 3 :(得分:0)

试试这个

SELECT ProductId, ProductName, imageId, imagePath
FROM product p
    INNER JOIN Image i 
        ON i.ProductId = p.ProductId
WHERE imageId IN
    (SELECT MIN(imageId) As imgId, ProductId
     FROM image
     GROUP BY ProductId
     )

答案 4 :(得分:0)

我们可以通过使用COMMON TABLE EXPRESSION使这个查询更加简化。我们也可以这样做

DECLARE @X TABLE (ProductID INT,ProductName VARCHAR(20))
INSERT INTO @x(ProductID,ProductName)VALUES (1,'Product1')
INSERT INTO @x(ProductID,ProductName)VALUES (2,'Product2')
select * from  @x
Declare @y TABLE(Imageid INT,ImagePath Varchar(20),ProductID INT)
INSERT INTO @y(Imageid,ImagePath,ProductID)VALUES (1,'Img1',1)
INSERT INTO @y(Imageid,ImagePath,ProductID)VALUES (2,'Img2',1)
INSERT INTO @y(Imageid,ImagePath,ProductID)VALUES (3,'Img3',2)
INSERT INTO @y(Imageid,ImagePath,ProductID)VALUES (4,'Img4',2)

;WITH CTE AS 
(
Select x.ProductID,x.ProductName,Y.Imageid,y.ImagePath from @X x
INNER JOIN @y Y
ON x.ProductID = Y.ProductID 
--GROUP BY x.ProductID,x.ProductName

)

Select ProductID,ProductName,MIN(Imageid),MIN(ImagePath) FROM CTE
GROUP BY ProductID,ProductName