2017-08-28 34 views
0

我有一个用户表,它与Areas具有多对多的关系。这种关系存储在Rel_User_area表中。我想显示用户名和区域列表中出现的第一个区域。例如,查询sql以获得多对多关系中的第一个匹配项

用户

id | Name  
1 | Peter  
2 | Joe 

id | Name  
1 | Area A  
2 | Area B 
3 | Area C 

Rel_User_area

iduser | idarea  
1  | 1  
1  | 3  
2  | 3 

我想要的结果:

User Name | Area  
Peter  |Area A  
Joe  |Area C 
+1

当按区域“id”排序时,是“第一”吗?就像你想为每个用户使用'min(area.id)',它是相应的名字。 – JNevill

+0

不一定,它必须是出现在关系表中的第一个。 – Dayana

+1

这就是问题所在。当记录被插入/删除时,首先进行更改。在桌子上有没有可以告诉我们的“TimeStamp”列/字段?请记住,表格中的数据是UNORDERED。您必须提供订单或订购方式。 – xQbert

回答

1

使用最小面积ID来确定“第一”,你可以使用相关子查询(引用字段(S)在主查询子查询过滤结果):

SELECT user.name, area.name 
FROM 
    user 
    INNER JOIN Rel_User_Area RUA ON user.id = RUA.iduser 
    INNER JOIN Area ON RUA.idarea = area.id 
WHERE area.id = (SELECT min(idarea) FROM Rel_User_Area WHERE iduser = RUA.iduser) 

有其他的做法可能是RDBMS特有的。就像在Teradata中一样,我会使用MySQL,SQL Server,Oracle,Postgres等中不存在的QUALIFY子句。无论RDBMS如何,上面都应该可以工作。

SELECT user.name, area.name 
FROM 
    user 
    INNER JOIN Rel_User_Area RUA ON user.id = RUA.iduser 
    INNER JOIN Area ON RUA.idarea = area.id 
QUALIFY ROW_NUMBER() OVER (PARTITION BY user.id ORDER BY area.id ASC) = 1; 
+0

它工作完美。谢谢 – Dayana

1

利用Rel_user_Area您在评论中提到的ID ...

这应该是相当独立的平台。

SELECT U.name as Username, A.Name as Area 
FROM (SELECT min(ID) minID, IDUser, IDarea 
     FROM Rel_user_Area 
     GROUP BY IDUser, IDarea) UA 
INNER JOIN User U 
on U.ID = UA.IDuser 
INNER JOIN Area A 
on A.ID = UA.IDArea 

如果跨应用和顶部工作(可替代限1比顶部如果PostgreSQL的或MySQL)

这将运行跨应用SQL一次在用户的每个记录;因此您可以获得每个用户最近的rel_user_Area ID。

SELECT U.name as Username, A.Name as Area 
FROM User U 
on U.ID = UA.IDuser 
CROSS APPLY (SELECT TOP 1 IDUser, IDArea 
      FROM Rel_user_Area z 
      WHERE Z.IDUSER = U.ID 
      ORDER BY ID ASC) UA 
INNER JOIN Area A 
on A.ID = UA.IDArea 
+0

谢谢你的回答。有效 :) – Dayana