这是我的第一张表:指纹
Serial UserID Name EmpID CardID Department Designation Status
1 626242 HariharanJ 626242 626242 IT Desktop Engineer Active
2 626243 RomiltonA 626243 626243 IT Desktop Engineer Active
这是我的第二张表:tblemployeepunch
fld_id fld_date fld_cardno fld_mode fld_punchdatetime
1 29122011 626242 01 2011-12-29 13:01:00
2 29122011 626243 01 2011-12-29 13:02:00
3 29122011 626242 02 2011-12-29 13:30:00
4 29122011 626243 02 2011-12-29 13:45:00
fld_mode 01表示intime 02表示停工时间 我需要以下输出:
Employee_Id Employee_Name Department Day Punchdate Intime Outtime
626242 HariharanJ IT Thursday 2011-12-29 13 : 01 13 : 30
626243 RomiltonA IT Thursday 2011-12-29 13 : 02 13 : 45
请帮帮我
答案 0 :(得分:2)
让我们做一些简化的假设,样本数据满足:
通过这些假设,您可以像这样对查询进行编码:
SELECT e.userid AS Employee_ID,
e.name AS Employee_Name,
e.Department AS Department,
DAYOFWEEK(i.fld_punchdatetime) AS Day,
TIME(i.fld_punchdatetime) AS InTime,
TIME(o.fld_punchdatetime) AS OutTime
FROM Fingerprints AS e
JOIN TblEmployeePunch AS i
ON e.userid = i.fld_cardno AND i.fld_mode = '01'
JOIN TblEmployeePunch AS o
ON e.userid = o.fld_cardno AND o.fld_mode = '02'
WHERE i.fld_date = o.fld_date;
函数名称需要验证;假设DAYOFWEEK()将返回传递给定日期时间值的星期几的字符串。同样,TIME()函数将返回传入的日期时间值的时间组件。您可能需要指定一些额外的参数只能获得小时和分钟(而不是包括秒数)。
如果人们不小心(并且他们)是关于签名/打卡的,那么您有登录并且不签名的人,以及其他签名并且不登录的人。在评论中,我建议一个FULL OUTER JOIN可以解决这个问题;我不确定这是一个三通UNION的好主意。以下代码适用于IBM Informix Dynamic Server(IDS),并在带有IDS 11.70.FC2的MacOS X 10.7.2上进行了测试。
我分阶段开发了查询,这就是我总是处理这样的复杂查询的方式。
SELECT i.Fld_CardNo AS UserID,
i.fld_punchdatetime AS i_time,
o.fld_punchdatetime AS o_time
FROM TblEmployeePunch AS i
JOIN TblEmployeePunch AS o
ON o.Fld_CardNo = i.Fld_CardNo AND i.Fld_Date = o.Fld_Date
WHERE i.fld_mode = '01' AND o.fld_mode = '02';
userid i_time o_time
626242 2011-12-29 13:01:00 2011-12-29 13:30:00
626243 2011-12-29 13:02:00 2011-12-29 13:45:00
SELECT i.Fld_Cardno AS UserID,
i.Fld_PunchDateTime AS i_time,
CAST(NULL AS DATETIME YEAR TO SECOND) AS o_time
FROM TblEmployeePunch AS i
WHERE NOT EXISTS
(SELECT *
FROM TblEmployeePunch AS o
WHERE o.Fld_Cardno = i.Fld_Cardno
AND o.Fld_Date = i.Fld_Date
AND o.Fld_Mode = '02'
)
AND i.fld_mode = '01';
userid i_time o_time
626247 2011-12-29 10:15:00
SELECT o.Fld_Cardno AS UserID,
CAST(NULL AS DATETIME YEAR TO SECOND) AS i_time,
o.Fld_PunchDateTime AS o_time
FROM TblEmployeePunch AS o
WHERE NOT EXISTS
(SELECT *
FROM TblEmployeePunch AS i
WHERE i.Fld_Cardno = o.Fld_Cardno
AND i.Fld_Date = o.Fld_Date
AND i.Fld_Mode = '01'
)
AND o.fld_mode = '02';
userid i_time o_time
626248 2011-12-29 11:05:00
SELECT i.Fld_CardNo AS UserID,
i.fld_punchdatetime AS i_time,
o.fld_punchdatetime AS o_time
FROM TblEmployeePunch AS i
JOIN TblEmployeePunch AS o
ON o.Fld_CardNo = i.Fld_CardNo AND i.Fld_Date = o.Fld_Date
WHERE i.fld_mode = '01' AND o.fld_mode = '02'
UNION
SELECT i.Fld_Cardno AS UserID,
i.Fld_PunchDateTime AS i_time,
CAST(NULL AS DATETIME YEAR TO SECOND) AS o_time
FROM TblEmployeePunch AS i
WHERE NOT EXISTS
(SELECT *
FROM TblEmployeePunch AS o
WHERE o.Fld_Cardno = i.Fld_Cardno
AND o.Fld_Date = i.Fld_Date
AND o.Fld_Mode = '02'
)
AND i.fld_mode = '01'
UNION
SELECT o.Fld_Cardno AS UserID,
CAST(NULL AS DATETIME YEAR TO SECOND) AS i_time,
o.Fld_PunchDateTime AS o_time
FROM TblEmployeePunch AS o
WHERE NOT EXISTS
(SELECT *
FROM TblEmployeePunch AS i
WHERE i.Fld_Cardno = o.Fld_Cardno
AND i.Fld_Date = o.Fld_Date
AND i.Fld_Mode = '01'
)
AND o.fld_mode = '02';
userid i_time o_time
626242 2011-12-29 13:01:00 2011-12-29 13:30:00
626243 2011-12-29 13:02:00 2011-12-29 13:45:00
626247 2011-12-29 10:15:00
626248 2011-12-29 11:05:00
将3路UNION与指纹表连接起来产生:
SELECT e.userid AS Employee_ID,
e.name AS Employee_Name,
e.Department AS Department,
DAYOFWEEK(t.i_time) AS Day,
TIME(t.i_time) AS InTime,
TIME(t.o_time) AS OutTime
FROM Fingerprints AS e
JOIN (SELECT i.Fld_CardNo AS UserID,
i.fld_punchdatetime AS i_time,
o.fld_punchdatetime AS o_time
FROM TblEmployeePunch AS i
JOIN TblEmployeePunch AS o
ON o.Fld_CardNo = i.Fld_CardNo AND i.Fld_Date = o.Fld_Date
WHERE i.fld_mode = '01' AND o.fld_mode = '02'
UNION
SELECT i.Fld_Cardno AS UserID,
i.Fld_PunchDateTime AS i_time,
CAST(NULL AS DATETIME YEAR TO SECOND) AS o_time
FROM TblEmployeePunch AS i
WHERE NOT EXISTS
(SELECT *
FROM TblEmployeePunch AS o
WHERE o.Fld_Cardno = i.Fld_Cardno
AND o.Fld_Date = i.Fld_Date
AND o.Fld_Mode = '02'
)
AND i.fld_mode = '01'
UNION
SELECT o.Fld_Cardno AS UserID,
CAST(NULL AS DATETIME YEAR TO SECOND) AS i_time,
o.Fld_PunchDateTime AS o_time
FROM TblEmployeePunch AS o
WHERE NOT EXISTS
(SELECT *
FROM TblEmployeePunch AS i
WHERE i.Fld_Cardno = o.Fld_Cardno
AND i.Fld_Date = o.Fld_Date
AND i.Fld_Mode = '01'
)
AND o.fld_mode = '02'
) AS t
ON e.userid = t.userid
ORDER BY e.userid;
employee_id employee_name department day intime outtime
626242 HariharanJ IT Thursday 13:01:00 13:30:00
626243 RomiltonA IT Thursday 13:02:00 13:45:00
626247 InnerJ IS Thursday 10:15:00
626248 OuterJ IS 11:05:00
哦,小提琴:当intime
为空时,星期几出现空。这可以修复;我将它作为练习留给读者。 (提示:COALESCE()或NVL()或者IFNULL()可能会在答案中找到答案。)
CREATE TABLE Fingerprints
(
Serial SERIAL NOT NULL PRIMARY KEY,
UserID INTEGER NOT NULL UNIQUE,
Name CHAR(15) NOT NULL,
EmpID INTEGER NOT NULL UNIQUE,
CardID INTEGER NOT NULL UNIQUE,
Department CHAR(10) NOT NULL,
Designation CHAR(20) NOT NULL,
Status CHAR(8) NOT NULL CHECK(Status IN ('Active', 'Inactive'))
);
INSERT INTO Fingerprints VALUES(1, 626242, "HariharanJ", 626242, 626242, "IT", "Desktop Engineer", "Active");
INSERT INTO Fingerprints VALUES(2, 626243, "RomiltonA", 626243, 626243, "IT", "Desktop Engineer", "Active");
INSERT INTO Fingerprints VALUES(3, 626247, "InnerJ", 626247, 626247, "IS", "Web Technician", "Active");
INSERT INTO Fingerprints VALUES(4, 626248, "OuterJ", 626248, 626248, "IS", "Web Technician", "Active");
CREATE TABLE TblEmployeePunch
(
Fld_ID SERIAL NOT NULL PRIMARY KEY,
Fld_Date INTEGER NOT NULL,
Fld_CardNo INTEGER NOT NULL REFERENCES Fingerprints(UserID),
Fld_Mode CHAR(2) NOT NULL,
Fld_PunchDateTime DATETIME YEAR TO SECOND NOT NULL
);
INSERT INTO TblEmployeePunch VALUES(1, 29122011, 626242, "01", "2011-12-29 13:01:00");
INSERT INTO TblEmployeePunch VALUES(2, 29122011, 626243, "01", "2011-12-29 13:02:00");
INSERT INTO TblEmployeePunch VALUES(3, 29122011, 626242, "02", "2011-12-29 13:30:00");
INSERT INTO TblEmployeePunch VALUES(4, 29122011, 626243, "02", "2011-12-29 13:45:00");
INSERT INTO TblEmployeePunch VALUES(5, 29122011, 626247, "01", "2011-12-29 10:15:00");
INSERT INTO TblEmployeePunch VALUES(6, 29122011, 626248, "02", "2011-12-29 11:05:00");
Informix不提供国际化的DAYOFWEEK功能,因此这里有替代品(也没有国际化)。可能使用TO_DATE()和适当的格式字符串来编写国际化版本。
CREATE PROCEDURE DayOfWeek(d DATE) RETURNING CHAR(9);
DEFINE dow INTEGER;
LET dow = WEEKDAY(d);
IF dow = 0 THEN RETURN "Sunday"; END IF;
IF dow = 1 THEN RETURN "Monday"; END IF;
IF dow = 2 THEN RETURN "Tuesday"; END IF;
IF dow = 3 THEN RETURN "Wednesday"; END IF;
IF dow = 4 THEN RETURN "Thursday"; END IF;
IF dow = 5 THEN RETURN "Friday"; END IF;
IF dow = 6 THEN RETURN "Saturday"; END IF;
RETURN NULL;
END PROCEDURE;
Informix使用一组类型,例如DATETIME YEAR TO SECOND而不是TIMESTAMP和DATETIME HOUR TO SECOND而不是TIME。此函数将'TIMESTAMP'转换为'TIME'。
CREATE PROCEDURE Time(dt DATETIME YEAR TO SECOND) RETURNING DATETIME HOUR TO SECOND;
RETURN EXTEND(dt, HOUR TO SECOND);
END PROCEDURE;