我的出勤数据包含用户名,时间和状态(IN
或OUT
)。我想显示包含姓名的签到数据以及签入/签出时间。我希望一个人每天最多可以进出两次。数据如下:
如您所见,我的问题是,对于同一登录尝试,一个人可以在不同的秒内拥有多个数据条目。这是因为我从指纹考勤扫描仪获取数据,并且在某些情况下机器会进行多次输入,有时只需5-10秒。我想选择这样的数据:
如何确定正确的登录尝试时间,然后选择数据透视表?
答案 0 :(得分:3)
首先,您需要通过删除重复的条目来规范化数据。在您的情况下,这是一个挑战,因为不容易将重复的数据标识为重复的数据。您可以做一些假设。在下面,我假设没有人会在两分钟的时间内进行多次登录尝试。您可以先使用通用表表达式(CTE,使用WITH
子句)来完成此操作。
在CTE中,您可以使用LAG
功能。本质上,这段代码说的是“对于用户和条目类型的每个分区,如果先前的值在该值的2分钟之内,则输入一个数字,否则输入null。”我选择null作为保留值的标志,因为第一项的LAG
将为null。因此,您的CTE只会返回不同尝试的条目事件(ID)表。
现在,您准备一个PIVOT
将从中提取的另一个CTE,其中包含表中的所有内容,但仅包含您关心的条目ID。 PIVOT
将查看您的IN / OUT时间的MIN / MAX。
WITH UNIQUE_LOGINS AS (
SELECT ID FROM LOGIN_TABLE
WHERE CASE WHEN LAG(TIME, 1, 0) OVER (PARTITION BY USERNAME, STATUS ORDER BY TIME)
+ (2/60/24) < TIME THEN NULL ELSE 1 END IS NULL ), -- Times within 2 minutes
TEMP_FOR_PIVOT AS (
SELECT USERNAME, TIME, STATUS FROM LOGIN_TABLE WHERE ID IN (SELECT ID FROM UNIQUE_LOGINS)
)
SELECT * FROM TEMP_FOR_PIVOT
PIVOT (
MIN(TIME), MAX(TIME) FOR STATUS IN ('IN', 'OUT')
)
从那里,如果您需要重新排列或重命名列,则只需将最后一个SELECT
放入另一个CTE中,然后从中选择值即可。这里还有关于PIVOT
的更多信息:Rotate/pivot table with aggregation in Oracle