我有一个审核表,其中记录了特定的操作(例如“访问”,“创建”,“更新”等)。我选择这些记录是为了使它们可以在表中显示给管理用户。
当我选择特定实体的所有记录时,此方法工作正常。但是,由于我使用的是Post-Redirect-Get模式,因此“访问”记录被记录在每个页面视图上。在典型的会话中,最终用户可能会在相同的5分钟窗口中点击相同的页面6或7次。结果,管理用户不得不滚动浏览相当多的冗余访问记录,这可以理解地分散了用户体验。
为解决此问题,我编写了两个查询。第一个将查找不是访问记录的所有记录。第二个将查找访问记录,然后将它们分为十分钟的间隔。然后,我UNION
这两个查询并按日期时间排序。
-- Select non 'access' records
SELECT
[ORIGIN_ID]
,[ORIGIN_ID_TYPE]
,[REFERENCE_ID]
,[REFERENCE_ID_TYPE]
,[ACTION_TYPE_ID]
,CAST([ORIGINAL_VALUE] AS VARCHAR(8000)) AS ORIGINAL_VALUE
,CAST([CHANGED_VALUE] AS VARCHAR(8000)) AS CHANGED_VALUE
,[CREATED_BY]
,[CREATED_ON]
FROM [HISTORY]
WHERE [ORIGIN_ID] = 500 AND [ORIGIN_ID_TYPE] = 4 AND [ACTION_TYPE_ID] != 1
UNION
-- Select 'access' records and group them into 10 minute intervals by ts
SELECT
[ORIGIN_ID]
,[ORIGIN_ID_TYPE]
,[REFERENCE_ID]
,[REFERENCE_ID_TYPE]
,[ACTION_TYPE_ID]
,CAST([ORIGINAL_VALUE] AS VARCHAR(255)) AS ORIGINAL_VALUE
,CAST([CHANGED_VALUE] AS VARCHAR(255)) AS CHANGED_VALUE
,[CREATED_BY]
,DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [CREATED_ON]) / 10 * 10, 0) AS CREATED_ON
FROM [HISTORY]
WHERE [ACTION_TYPE_ID] = 1 AND [ORIGIN_ID] = 500 AND [ORIGIN_ID_TYPE] = 4
GROUP BY
[ORIGIN_ID]
,[ORIGIN_ID_TYPE]
,[REFERENCE_ID]
,[REFERENCE_ID_TYPE]
,[ACTION_TYPE_ID]
,CAST([ORIGINAL_VALUE] AS VARCHAR(255))
,CAST([CHANGED_VALUE] AS VARCHAR(255))
,[CREATED_BY]
,DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [CREATED_ON]) / 10 * 10, 0)
ORDER BY [CREATED_ON] DESC
SQLFiddle(SQLFiddle允许我上传的数据量有限)
我觉得可能有一种更好的方法可以不需要我使用UNION
。为了做到这一点,我不得不将TEXT
列转换为VARCHAR
列,我觉得可能会有更好的选择。关于如何改进此查询的任何建议?
答案 0 :(得分:0)
使用这两个分组消除联合。第二个也成为合并的{model: 'Village', id: '64'}
列的新表达式。第一个也可以用于控制排序,然后以其他方式丢弃。 (也不要忘记删除created_on
上的过滤器。):
action_type_id
这将导致查询出于聚合目的将两种类型的操作视为不同。由于您确实希望每一行都采用非1的动作,因此您根本不会将这些行折叠成10分钟的方块。
请注意,如果可以用相同的时间戳记录两个这样的行,这将无法正常工作。您需要对另一个ID(或仅case when action_type_id <> 1 then 1 else 2 end,
case when action_type_id <> 1
then created_on
else DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [CREATED_ON]) / 10 * 10, 0)
end
)进行分组以解决该问题,但我怀疑这是不必要的。