0

我想从下表生成 csv 文件中的报告。

   CARDNO       |      PAYCODE          |               OFFICEPUNCH
  00001210      |       1210            |           6/22/2012 9:49:00 AM     
  00001210      |       1210            |           6/22/2012 7:58:00 PM     
  00001211      |       1211            |           6/23/2012 9:31:00 AM     
  00001211      |       1211            |           6/23/2012 6:12:00 PM   

它保存了员工打卡数据,每张卡打卡存储在一行中,因此如果用户员工在早上打卡它会标记为In time,但同一天最后一次打卡将被视为Out time,一些时间员工打卡有卡很多次。所以我需要采取第一次和最后一次打卡时间。

问题

我想获得以下格式的 CSV

  Date     |  PayCode |   Card No   |   Intime  | Outtime  | Hrs Works
2012-06-22 |  1210    |   00001210  |   9:30    | 18:00    |  7.3 
2012-06-22 |  1211    |   00001211  |   9:30    | 18:00    |  7.3 
2012-06-23 |  1210    |   00001210  |   9:30    | 18:00    |  7.3 
2012-06-23 |  1211    |   00001211  |   9:30    | 18:00    |  7.3 
2012-06-24 |  1210    |   00001210  |   9:30    | 18:00    |  7.3 
2012-06-24 |  1211    |   00001211  |   9:30    | 18:00    |  7.3 
                                                                ... and continue 

请帮助我如何获得上述结果,我已经通过代码尝试过,但我无法实现它。

请使用 sql 查询发布。

4

4 回答 4

1

用SQL做逻辑不是更容易吗?

按 PAYCODE 和 OFFICEPUNCH 分组(也许按 OFFICEPUNCH 并截断时间),然后您可以为 Time In 执行 MIN(OFFICEPUNCH),为 Time Out 执行 MAX(OFFICEPUNCH)。

编辑

SQL 示例:

SELECT DISTINCT
    CONVERT(VARCHAR(10), OFFICEPUNCH, 20) AS 'PunchDate'
INTO
    #Date
FROM
    MachineRawPunch
WHERE
    OFFICEPUNCH >= @p_StartDate
AND
    OFFICEPUNCH <= @p_EndDate

SELECT
    #Date.PunchDate AS 'Date',
    TblEmployee.PAYCODE,
    TblEmployee.PRESENTCARDNO AS 'CardNo',
    MIN(CASE MachineRawPunch.ISMANUAL WHEN 'Y' THEN MachineRawPunch.OFFICEPUNCH ELSE CAST(#Date.PunchDate + ' 9:30' AS datetime) END) AS 'TimeIn',
    CASE WHEN MachineRawPunch.ISMANUAL = 'N' THEN CAST(#Date.PunchDate + ' 18:00' AS datetime)
         WHEN MAX(MachineRawPunch.OFFICEPUNCH) > MIN(MachineRawPunch.OFFICEPUNCH)
         THEN MAX(MachineRawPunch.OFFICEPUNCH)
         ELSE NULL END AS 'TimeOut'
FROM
    #Date
CROSS JOIN
    TblEmployee
LEFT JOIN
    MachineRawPunch
ON
    MachineRawPunch.PAYCODE = TblEmployee.PAYCODE
AND
    CONVERT(VARCHAR(10), MachineRawPunch.OFFICEPUNCH, 20) = #Date.PunchDate
GROUP BY
    #Date.PunchDate,
    TblEmployee.PAYCODE,
    TblEmployee.PRESENTCARDNO
ORDER BY
    #Date.PunchDate,
    TblEmployee.PAYCODE,
    TblEmployee.PRESENTCARDNO

DROP TABLE #Date

环形

while (sqlReader.Read())
{
    // get the results of each column
    string date = (string)sqlReader["Date"];
    string cardNumber = sqlReader["CARDNO"] == DBNull.Value ? string.Empty : (string)sqlReader["CARDNO"];
    DateTime inTime = sqlReader["TimeIn"] == DBNull.Value ? DateTime.MinValue : (DateTime)sqlReader["TimeIn"];
    DateTime outTime = sqlReader["TimeOut"] == DBNull.Value ? DateTime.MinValue : (DateTime)sqlReader["TimeOut"];
    string payCode = (string)sqlReader["PAYCODE"];

    //Stores single row as string 
    int hrsWorked = outTime == DateTime.MinValue ? 0 : outTime.Subtract(inTime).Hours;
    int minsWorked = outTime == DateTime.MinValue ? 0 : outTime.Subtract(inTime).Minutes;
    strRow = date + "," +
             payCode + "," +
             cardNumber + "," +
             (inTime == DateTime.MinValue ? string.Empty : inTime.ToString("H:mm")) + "," +
             (outTime == DateTime.MinValue ? string.Empty : outTime.ToString("H:mm")) + ", " +
             hrsWorked + "." + minsWorked + " , Staus";
    Console.WriteLine(strRow);
    //Write to file
    // sw.WriteLine(strRow);
    i++;
}
于 2012-06-25T11:24:58.157 回答
1
select  *
,       datediff(minute, first_in, last_out) as duration
from    (
        select  emp_reader_id
        ,       min(case when Event_entry.event_entry_name = 'IN' then trnevents.DT end) as first_in
        ,       max(case when Event_entry.event_entry_name = 'OUT' then trnevents.DT end) as last_out
        ,       cast(min(trnevents.DT) as date) as date
        from    trnevents inner join Event_entry on trnevents.EventCatId=Event_entry.EventCatId
        group by
                emp_reader_id
        ,       cast(trnevents.DT as date)
        ) as SubQueriesMustBeNamed
        select * from trnevents
于 2017-12-10T12:17:48.317 回答
0

单个查询就足够了:

select
    PAYCODE, CARDNO,
    min(officepunch) as INtime,
    max(officepunch) as OutTime,
    timediff(max(officepunch),min(officepunch)) as HRSWork 
FROM database.tablename 
group by CARDNO, PAYCODE, cast(officepunch as date) 
order by cardno;
于 2013-08-21T07:04:18.393 回答
0

在 Sql 中进行最小/最大和分组可能会更容易。

但以防万一你在代码中完成它我会做这样的事情:

创建一个方法以将数据作为可枚举行返回:

public IEnumerable<IDataRecord> ExecuteSelect()
{
  cmd = new SqlCommand();
  cmd.Connection = con;
  cmd.CommandText = "SELECT CARDNO, OFFICEPUNCH, PAYCODE FROM MachineRawPunch WHERE OFFICEPUNCH >= @p_StartDate AND OFFICEPUNCH <= @p_EndDate ORDER BY PAYCODE, OFFICEPUNCH";
  cmd.Parameters.Add("@p_StartDate", SqlDbType.DateTime).Value = startDate.Date;
  cmd.Parameters.Add("@p_EndDate", SqlDbType.DateTime).Value = endDate.Date.AddDays(1);

  using (var reader = cmd.ExecuteReader())
  {
    while (reader.Read()) yield return reader;
  }
}

然后在您的导出按钮单击事件中使用 linq 使用 min 和 max 做一个漂亮的组。从这里开始,您应该能够进行其余的格式化和操作:

private void buttonExport_Click(object sender, EventArgs e)
{
  //Selects the rows into a list of typed objects. Easier for querying below:
  var rows =
    ExecuteSelect().Select(
      r =>
      new
        {
          CardNo = (string) r["CARDNO"],
          OfficePunch = (DateTime) r["OFFICEPUNCH"],
          PayCode = (string) r["PAYCODE"]
        }).ToList();

  var groupedRows = (from r in rows
                     group r by new {r.CardNo, r.OfficePunch}
                     into g
                     select new
                              {
                                CardNo = g.Select(f => f.CardNo).FirstOrDefault(),
                                PayCode = g.Select(f => f.PayCode).FirstOrDefault(),
                                InDateTime = g.Min(min => min.OfficePunch),
                                OutDateTime = g.Max(max => max.OfficePunch)
                              }).ToList();

  foreach (var row in groupedRows)
  {
    //write to CSV
    //row.CardNo, row.PayCode, row.InDateTime, row.OutDateTime
  }
}

我希望这能引导你朝着正确的方向前进。基本上剩下的就是将日期格式化为时间并计算小时数。

于 2012-06-25T12:05:27.107 回答