SQL - 为每个匹配返回一行

时间:2012-06-30 06:49:44

标签: sql-server

我不完全确定如何说出我正在寻找的正在使搜索变得困难的东西。但我要做的是为每个不同的列匹配返回一条记录

表格结构:

ItemHolderId Name
------------ --------------------------------------------------
1            Holder A
2            Holder B


ItemId      Data                                               ItemHolderId
----------- -------------------------------------------------- ------------
1           Item A                                             1
2           Item B                                             1
3           Item C                                             1
4           Item D                                             1
5           Item E                                             2
6           Item F                                             2
7           Item G                                             2

我希望为每个商品持有人ID选择一个商品。因此,它只会选择项目A和项目E.订单对于每个匹配列只有一条记录并不重要。我希望我能以明智的方式解释这一点。

感谢您的时间。

3 个答案:

答案 0 :(得分:2)

您可以使用row_number()对用户进行数据分区,然后使用' 1'来抓取每条记录。作为[rank]。通过这种方式,您可以控制数据的分区和排序,以控制哪个记录的值为' 1',从而返回......

/* Setup tables for query */
declare @tbl1 table (ItemHolderId int, Name varchar(32))
declare @tbl2 table (ItemId int, Data varchar(32), ItemHolderId int)

insert into @tbl1 values (1, 'Holder A'), (2, 'Holder B')

insert into @tbl2 values (1, 'Item A', 1), (2, 'Item B', 1), (3, 'Item C', 1), (4, 'Item D', 1)
insert into @tbl2 values (5, 'Item E', 2), (6, 'Item F', 2), (7, 'Item G', 2)

/* Select data */
select t2.*, row_number() over (partition by t1.ItemHolderId order by t2.ItemHolderId) as [rank]
into #temp
from @tbl1 t1 inner join @tbl2 t2 on t1.ItemHolderId = t2.ItemHolderId

select ItemId, Data, ItemHolderId from #temp where [rank] = 1

drop table #temp

答案 1 :(得分:1)

一种方法是使用CTE(公用表表达式),如果您使用的是SQL Server 2005 且更新(在这方面您不够具体)。

使用此CTE,您可以按照某些条件对数据进行分区 - 即ItemHolderId - 并为每个分区的所有行启用SQL Server编号,按其他一些条件排序(您需要< em>一些标准 - 你使用哪一个取决于你。)

所以尝试这样的事情:

;WITH PartitionedComponents AS
(
   SELECT 
       ih.ItemHolderID, ih.Name, d.Data,
       ROW_NUMBER() OVER(PARTITION BY ih.ItemHolderID ORDER BY d.Data DESC) AS 'RowNum'
   FROM 
       dbo.ItemHolder ih
   INNER JOIN 
       dbo.ItemHolderData d ON ih.ItemHolderID = d.ItemHolderID
   WHERE
       ComponentId IN (.....) 
       AND ConsoleTimeStamp <= (threshold)
)
SELECT 
   ItemHolderID, Name, Data
FROM 
   PartitionedComponents
WHERE
   RowNum = 1

在这里,我只选择每个“分区”的最后两个条目(即每个ItemHolderId) - 由“数据”列按降序排序。

这会接近你想要的吗?

答案 2 :(得分:0)

我认为你也可以对itemholderid列使用group by函数,这对我来说很有帮助。

select 
   rownum itemId, 
   tmp.name , 
   tmp.itemholderid  
from 
   (select 
       min(t.name) name, 
       t.itemholderid  
    from 
       table_name t 
    group by t.itemholderid
   )tmp;