Выберите отличный по внешнему ключу, внутреннее объединение другой таблицы - PullRequest
2 голосов
/ 09 июля 2019

В основном я хочу выбрать 3 последних действия, выполненных пользователем. Но нет дубликатов в RelationId, а также внутренних разрешений, чтобы убедиться, что у пользователя есть разрешение на выполнение того же действия.

Единственное, что я хочу от разрешения - это RelationId.

Не дублируя, я имею в виду, что если есть две строки Action с одинаковым RelationId, следует выбрать одну из них, закрывающуюся наверх (Ordered by 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 ONLY

По какой-то причине это не работает, потому что я получаю дубликаты на 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 голосов
/ 09 июля 2019

Решил это, сделав это. Не знаю, если это лучшее решение.

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
0 голосов
/ 09 июля 2019

Если я его получу, вам потребуется для каждого Разрешения только самое последнее действие, и из всех них сохраняются самые последние три строки. Здесь:

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
0 голосов
/ 09 июля 2019

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
)
0 голосов
/ 09 июля 2019

Из вашего определения последних 3 на пользователя (если последние 3, то это не может быть одна строка на отношение ID):

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;
...