如何隐藏现有数据中的24小时到12小时

时间:2019-06-11 08:48:27

标签: sql sql-server tsql

我想知道我的sql这样的问题,我的问题是每当我删除代码中的where子句时都会出现错误(从字符串转换日期和/或时间时转换失败。)我删除了where子句,因为我要查看我的所有数据,下图仅是示例,我有这么多数据

这是第一张桌子

| Entries               | recordDate              | Empid  | Reference |             
+-----------------------+-------------------------+--------+-----------+  
| 0016930507201907:35I  | 2019-05-07 00:00:00 000 | 001693 |   1693    |  
| 0016930507201917:06O  | 2019-05-07 00:00:00 000 | 001693 |   1693    |  
| 0016930507201907:35I  | 2019-05-08 00:00:00 000 | 001693 |   1693    |  
|                       | 2019-05-08 00:00:00 000 | 001693 |   1693    |

第二张桌子

| LastName | FirstName | middleName | EmployeeNO |
+----------+-----------+------------+------------+
| Cruz     | MA Kimberly  | Castillo   |   001693   |

这是我想看到的

| Name                    | EmployeeNO | RecordDate              | TimeIn | TimeOut | 
+-------------------------+------------+-------------------------+--------+---------+
| CRUZ, MA  KIMBERLY, CASTILLO  |    001693  | 2019-05-07 00:00:00 000 |  07:35am |  05:06pm  |
| CRUZ, MA  KIMBERLY,CASTILLO   |    001693  | 2019-05-08 00:00:00 000 |  07:35am |

这是我的代码,请帮助我,谢谢您的帮助

Select 
    B.LastName + ',' + B.FirstName + ',' + B.MiddleName[Name] ,
    A.[RecordDate],
    B.[EmployeeNO],
    CONVERT(VARCHAR(08),MIN(IIF(ISNULL(CHARINDEX('I', A.[Entries], 0), 1) > 0, CAST( SUBSTRING(A.[Entries], LEN(A.[Entries]) - 5, 5) AS [TIME]), NULL)), 100) AS [TimeIn], 
    CONVERT(VARCHAR(08),MAX(IIF(ISNULL(CHARINDEX('O', A.[Entries], 0), 1) > 0,CAST(SUBSTRING(A.[Entries], LEN(A.[Entries]) - 5, 5) AS [TIME]), NULL)),100) AS [TimeOut]
FROM Employees [B]
INNER JOIN [DTR Upload] [A] ON B.EmployeeNo = A.EmpID
GROUP BY B.LastName, B.FirstName, B.MiddleName,B.[EmployeeNO], A.[recordDate]
ORDER BY A.[recordDate] asc, B.LastName +','+B.FirstName + ','+ B.MiddleName ASC

2 个答案:

答案 0 :(得分:0)

这适用于您提供的示例数据。 注意,但是,我假设 recordDatevarchar,因为它不是有效的datetime值(如果它是,则2019-05-07 00:00:00 0002019-05-07 00:00:00.000;请注意,.而非)。如果recordDate不是varchar,则无需包含STUFFCONVERT表达式即可“固定” VALUES中的值操作员。但是,实际上,您不应该将date(time)数据存储为varchar。为数据使用适当的数据类型(因为这些值除午夜以外没有其他时间部分,因此date似乎是最好的选择。)

我还返回TimeInTimeOut列作为数据类型time。在SQL Server中,日期和时间数据类型没有格式,它们是二进制值。如果要以12小时格式显示它,则需要在表示层而不是SQL中进行配置:

--Table1 Sample Data
WITH Table1 AS(
    SELECT V.Entries,
           V.recordDate,
           V.Empid,
           V.Reference
    FROM (VALUES('0016930507201907:35I','2019-05-07 00:00:00 000','001693',1693),  
                ('0016930507201917:06O','2019-05-07 00:00:00 000','001693',1693),  
                ('0016930507201907:35I','2019-05-08 00:00:00 000','001693',1693),  
                (NULL,'2019-05-08 00:00:00 000','001693',1693)) V(Entries,recordDate,Empid,Reference)),
--Table2 Sample Data
Table2 AS (
    SELECT 'Cruz' AS LastName,
           'MA Kimberly' AS FirstName,
           'Castillo' AS middleName,
           '001693' AS EmployeeNO)
--Solution
SELECT STUFF(CONCAT(', ' + T2.LastName, ', ' + T2.FirstName, ', ' + T2.middleName),1,2,'') AS [Name],
       T2.EmployeeNO,
       T1.recordDate,
       MAX(CONVERT(time(0),CASE S.InOut WHEN 'I' THEN SUBSTRING(T1.Entries,15,5) END)) AS TimeIn,
       MAX(CONVERT(time(0),CASE S.InOut WHEN 'O' THEN SUBSTRING(T1.Entries,15,5) END)) AS TimeOut
FROM Table1 T1
     JOIN Table2 T2 ON T1.Empid = T2.EmployeeNO --These should really have the same name
     CROSS APPLY(VALUES(CONVERT(datetime,STUFF(STUFF(T1.recordDate,11,1, 'T'),20,1,'.')),RIGHT(T1.Entries,1))) S(recordDate, InOut)
GROUP BY T2.EmployeeNO,
         T1.recordDate,
         T2.LastName,
         T2.FirstName,
         T2.middleName;

答案 1 :(得分:0)

那是你的追随吗?

;WITH CTE AS
(
  SELECT EmployeeNO,
         CONCAT(LastName, ',', FirstName, ',', MiddleName) Name,
         RecordDate,
         CASE WHEN RIGHT(Entries, 1) = 'I' 
              THEN CAST(REPLACE(RIGHT(Entries, 6), 'I', '') AS TIME)
         END TimeIn,
         CASE WHEN RIGHT(Entries, 1) = 'O' 
              THEN CAST(REPLACE(RIGHT(Entries, 6), 'O', '') AS TIME)
         END TimeOut     
  FROM T1 INNER JOIN T2
  ON T1.EmpId = T2.EmployeeNO
)
SELECT EmployeeNO,
       Name,
       RecordDate,
       MIN(TimeIn) TimeIn,
       MAX(TimeOut) TimeOut
FROM CTE
GROUP BY EmployeeNO,
         Name,
         RecordDate;

返回:

+------------+------------------------+-------------------------+----------+----------+
| EmployeeNO |          Name          |       RecordDate        |  TimeIn  | TimeOut  |
+------------+------------------------+-------------------------+----------+----------+
|       1693 | Cruz,Kimberly,Castillo | 2019-05-07 00:00:00 000 | 07:35:00 | 17:06:00 |
|       1693 | Cruz,Kimberly,Castillo | 2019-05-08 00:00:00 000 | 07:35:00 |          |
+------------+------------------------+-------------------------+----------+----------+

Live Demo


现在,让我们谈谈您遇到的实际问题。

您将日期存储为字符串是不好的,请始终为数据选择正确的数据类型,因此您需要将日期存储为DATE。同样,对于Entries那里有3条信息,这意味着缺少规范化,因为它应该是3列。 例如

+----------------+------+---------------------+
|    Entries     | Kind |      EntriesDate    |
+----------------+------+---------------------+
| 00169305072019 |    1 | 2019-05-07 07:35:00 |
| 00169305072019 |    0 | 2019-05-07 16:30:00 |
+----------------+------+---------------------+

这样,您就不会陷入那些问题,事情变得简单。

对于名称的串联,如果您始终需要获取全名,我建议您为此使用一个计算列,那么就不必每次都将名称串联起来

ALTER TABLE <Your Table Name Here>
ADD [FullName] AS CONCAT(LastName, ',', FirstName, ',', MiddleName);