唯一SQL查询的问题

时间:2011-04-30 07:34:31

标签: sql-server sql-server-2005

我想选择所有记录,但查询只返回每个产品名称的一条记录。我的表类似于:

SellId   ProductName Comment
1          Cake        dasd 
2          Cake        dasdasd
3          Bread       dasdasdd  

其中产品名称不唯一。我希望查询为每个ProductName返回一条记录,其结果如下:

SellId   ProductName Comment
1          Cake        dasd 
3          Bread       dasdasdd 

我试过这个查询,

Select distict ProductName,Comment ,SellId from TBL#Sells

但它返回具有相同ProductName的多个记录。我的表并不像这样简单,这只是一个例子。解决办法是什么?它清楚了吗?

4 个答案:

答案 0 :(得分:2)

SELECT S.ProductName, S.Comment, S.SellId
FROM
   Sells S
   JOIN (SELECT MAX(SellId)
        FROM Sells
        GROUP BY ProductName) AS TopSell ON TopSell.SellId = S.SellId

这将获得最新评论作为您选择的评论,假设SellId是一个自动递增的身份上升。

答案 1 :(得分:2)

Select  ProductName, 
min(Comment) , min(SellId) from TBL#Sells
group by ProductName

如果您只需要每个产品名称一条记录,那么您必须为其他字段选择所需的值。

如果您聚合(使用分组依据),您可以选择aggregate function, htat是一个函数,它接受一个值列表并只返回一个:这里我选择了MIN:这是每个字段的最小walue。

注意:评论和卖出可以来自不同的记录,因为MIN是......

您可能觉得有用的Othter聚合:

FIRST : first record encountered
LAST : last record encoutered
AVG : average 
COUNT : number of records

第一个/最后一个具有所有字段来自同一记录的优势。

答案 2 :(得分:0)

我知道,你已经得到了答案,在类似的情况下,我想提供一种在性能方面最快的方法。我假设SellId是主键和身份。您需要ProductName上的索引才能获得最佳性能。

select 
    Sells.* 
from 
(
    select 
        distinct ProductName 
    from 
        Sells
) x
join 
    Sells 
on 
    Sells.ProductName = x.ProductName
    and Sells.SellId =
    (
        select 
            top 1 s2.SellId 
        from 
            Sells s2 
        where 
            x.ProductName = s2.ProductName 
        Order By SellId
    )

一个较慢的方法(但仍然比长字符列上的Group By和MIN更好)是:

select 
    * 
from
(
    select 
        *,ROW_NUMBER() over (PARTITION BY ProductName order by SellId) OccurenceId 
    from sells
) x
where 
    OccurenceId = 1

这个的一个优点是它更容易阅读。

答案 3 :(得分:0)

create table Sale
(
    SaleId int not null
        constraint PK_Sale primary key,
    ProductName varchar(100) not null,
    Comment varchar(100) not null
)

insert Sale
values
    (1, 'Cake', 'dasd'),
    (2, 'Cake', 'dasdasd'),
    (3, 'Bread', 'dasdasdd')

-- Option #1 with over()
select *
from Sale
where SaleId in
(
    select SaleId
    from
    (
        select SaleId, row_number() over(partition by ProductName order by SaleId) RowNumber
        from Sale
    ) tt
    where RowNumber = 1
)
order by SaleId

-- Option #2
select *
from Sale
where SaleId in
(
    select min(SaleId)
    from Sale
    group by ProductName
)       
order by SaleId

drop table Sale