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   

従業員のパンチデータ、すべてのカードパンチストアが連続して保持されるため、ユーザーの従業員が朝にカードをパンチした場合、そのカードは時間内としてマークされますが、同じ日付の最後のパンチはアウトタイムと見なされ、従業員がパンチする時間もありますそこに何度もカード。だから私は最初と最後のパンチ時間をとる必要があります。

問題

以下の形式で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で)、タイムアウトの場合はMIN(OFFICEPUNCH)、タイムアウトの場合は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

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を使用して最小値と最大値で気の利いたグループを実行します。これ以降、残りのフォーマットと操作を実行できるはずです。

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 に答える
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 に答える