在外键上选择不同的,内部联接另一个表

时间:2019-07-09 11:34:15

标签: sql sql-server inner-join distinct

基本上我想做的是,选择用户最后执行的3个操作。但是,RelationId上没有重复项,也没有内部联接权限,只是为了确保用户仍然有权执行相同的操作。

我唯一需要许可的是RelationId。

没有重复,我的意思是,如果有两行具有相同RelationId的Action,则应选择最接近顶部的一行(按TimeStamp排序)。

到目前为止,我想出了什么:

SELECT DISTINCT a.*, p.RelationId
FROM [Action] [a]
INNER JOIN [Permission] p 
  ON ([p].[RelationId] = [a].[RelationId] 
  AND [p].[RelationType] = [a].[RelationType] 
  AND [p].[UserId] = [a].[UserId] 
  AND [p].[Deleted] = 0)
WHERE [a].[ActionType] = 'Clicked' 
AND [a].[RelationType] = 'Direct' 
AND [a].[UserId] = 5 
AND [a].[Deleted] = 0
ORDER BY [a].[TimeStamp] DESC
OFFSET 0 ROWS
FETCH NEXT 3 ROWS ONLY

它只需要使用OFFSET X ROWS和FETCH NEXT 3 ROWS进行分页

由于某些原因,此方法不起作用,因为我在RelationId上得到了重复项。 没有错误。

示例数据:

action (
    id            INTEGER       PRIMARY KEY,
    ActionType    VARCHAR(50)   not null,
    RelationId    INTEGER       ForeignKey,
    Deleted       Bit           not null,
    TimeStamp     DATE          not null,
    UserId        INTEGER       ForeignKey
);

所需结果:一个用户的最后3个操作,每个用户对其具有的权限都取决于RelationId。

4 个答案:

答案 0 :(得分:0)

根据您对每个用户的后3个定义(如果为前3个,则每个RelationId不能为一行):

with data as (
  SELECT *, 
  row_number() over (partition by relationId order by [timeStamp] desc) as rNo
  from action 
  where [ActionType] = 'Clicked' AND 
        [RelationType] = 'Direct' AND 
        [UserId] = 5 AND 
        [Deleted] = 0
)
select a.id,a.ActionType,a.RelationId,a.Deleted,a.TimeStamp,a.UserId,
       p.RelationId as pRelId
FROM [data] [a]
INNER JOIN [Permission] p ON ([p].[RelationId] = [a].[RelationId] AND [p].[RelationType] = [a].[RelationType] AND [p].[UserId] = [a].[UserId]) 
WHERE p.[Deleted] = 0 and a.rNo <= 3
ORDER BY [a].[TimeStamp] DESC;

答案 1 :(得分:0)

如果我明白了,您只需为每个权限执行最新操作,然后从所有这些操作中保留最新的三行。在这里:

select top 3 p.RelationId,top_action.*
from 
    [Permission] p
    cross apply
    (
        select top 1 *
        from [Action] [a]
        where 
            [p].[RelationId] = [a].[RelationId] AND [p].[RelationType] = [a].[RelationType] AND [p].[UserId] = [a].[UserId] 
            and [a].[ActionType] = 'Clicked' AND [a].[RelationType] = 'Direct' AND [a].[UserId] = 5 AND [a].[Deleted] = 0
        order by [a].[TimeStamp] DESC
    )top_action
where [p].[Deleted] = 0
order by top_action.[TimeStamp] DESC

答案 2 :(得分:0)

Distinct将始终区分所有参数。选择*将始终不同。 您只需选择一个参数即可确定。

您可以使用分组依据,也可以使用相同的选择在两个步骤中简单地进行分组。像这样:

select * from Action where id in (
SELECT DISTINCT a.id
FROM [Action] [a]
INNER JOIN [Permission] p 
  ON ([p].[RelationId] = [a].[RelationId] 
  AND [p].[RelationType] = [a].[RelationType] 
  AND [p].[UserId] = [a].[UserId] 
  AND [p].[Deleted] = 0)
WHERE [a].[ActionType] = 'Clicked' 
AND [a].[RelationType] = 'Direct' 
AND [a].[UserId] = 5 
AND [a].[Deleted] = 0
ORDER BY [a].[TimeStamp] DESC
OFFSET 0 ROWS
FETCH NEXT 3 ROWS ONLY
)

答案 3 :(得分:0)

通过解决此问题。虽然不知道它是否是最好的解决方案。

SELECT [a].*, [p].[Id]
FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY [RelationId] ORDER BY [TimeStamp] DESC) AS row from [Action]) a
INNER JOIN [Permission] p ON ([ep].[RelationId] = [a].[RelationId] AND [p].[RelationType] = [a].[RelationType] AND [p].[UserId] = [a].[UserId] AND [p].[Deleted] = 0)
WHERE row = 1 AND [a].[ActionType] = 'Clicked' AND [a].[RelationType] = 'Direct' AND [a].[UserId] = 5 AND [a].[Deleted] = 0
ORDER BY [a].[TimeStamp] DESC
OFFSET 0 ROWS
FETCH NEXT 3 ROWS ONLY