2016-03-22 23 views
0

Kullanıcı giriş ve çıkış zamanlamalarının kayıt cihazı olduğu bir çalışan giriş sistemi geliştiriyorum. Belirli bir ayın bir çalışanının toplam çalışma saatlerini sorgulamak istediğim aşağıdaki mySql tablo şemasına sahibim.mySql, tarih farkının toplamını hesaplar

AttendanceId UserId Operation CreatedDate 
24     4  1  2016-03-20 23:18:59 
25     4  2  2016-03-20 23:19:50 
26     4  1  2016-03-20 23:20:28 
27     4  2  2016-03-20 23:20:31 

İşlem 1, giriş içindir ve işlem 2, kullanıma hazırdır. Bu sorguyu oluşturmama yardımcı olabilir misiniz?

+2

Bir çalışan 31'inci sırada denetler ve 1'i denetlerse ne olur? – Strawberry

+0

@Strawberry Bu şeyi unuttum. Aynı fikir veya daha iyi bir şema önerir misiniz? –

+0

Sadece soruya cevap verin. Ya da yapma. Sana kalmış. – Strawberry

cevap

0

Hoş bir şekilde karmaşık bir soru, teşekkürler. Benim sorgu ile ilgilenir:

  • Saatlerde kesin olarak ölçülemeyen dikkat edin. Hesaplamanın sonunda saniye sayısı toplam ve 3600'e bölünür. ya sonunda aylık sınırını kapsayan
  • Yarışmaya (teşekkürler strawberry) başlamıştır geçerli ayda
  • Yarışmaya (operasyonla bir giriş yoktur "1") ancak henüz bitmiş değil (hiçbir karşılık gelen operasyon "2 var ").

Ben test için aşağıdaki verileri kullanılmıştır:

INSERT INTO Attendance(UserId, Operation, CreatedDate) VALUES 
(4, 1, '2016-01-01 15:00:00'), 
(4, 2, '2016-01-01 19:00:00'), 
(4, 1, '2016-01-31 23:00:00'), 
(4, 2, '2016-02-01 01:00:00'), 
(4, 1, '2016-02-20 23:18:59'), 
(4, 2, '2016-02-20 23:19:50'), 
(4, 1, '2016-02-20 23:20:28'), 
(4, 2, '2016-02-20 23:20:31'), 
(4, 1, '2016-02-29 23:00:00'), 
(4, 2, '2016-03-01 01:00:00'), 
(4, 1, '2016-03-02 15:00:00'), 
(4, 2, '2016-03-02 18:00:00'), 
(4, 1, '2016-03-22 10:00:00'); 

sorgu belirli bir ay boyunca tüm kullanıcıların saatlerini seçer. Bir sorguda bir aydan fazla bir süre için sonuçların seçilmesi, katılımcıların ay sınırlarını kapsadığı ve gerektiğinde aylar boyunca yinelemenin ve sorguyu tekrar tekrar çalıştırarak SQL'de uygun şekilde dört tarihin ayarlanması olasılığı nedeniyle daha karmaşıktır.

En içteki sorgu tüm varış zamanlarını ve tüm kullanıcılar için ilgili kalkış saatini seçer. Dış sorgu daha sonra onları mevcut ay ile kısıtlar, iki kez arasındaki farkı hesaplar ve bunları kullanıcı tarafından toplar.

SELECT UserId, SUM(TIMESTAMPDIFF(
    SECOND, 
    GREATEST(TimeIn, '2016-02-01'), 
    LEAST(COALESCE(TimeOut, NOW()), '2016-03-01')))/3600 HoursInMonth 
FROM (SELECT TimeIn.UserId, TimeIn.CreatedDate TimeIn, MIN(TimeOut.CreatedDate) TimeOut 
     FROM Attendance TimeIn 
     LEFT JOIN Attendance TimeOut ON TimeOut.UserId = TimeIn.UserId 
            AND TimeOut.Operation = 2 
            AND TimeOut.CreatedDate > TimeIn.CreatedDate 
     WHERE TimeIn.operation = 1 
     GROUP BY TimeIn.AttendanceId 
     ORDER BY TimeIn.CreatedDate) TimeInOut 
WHERE DATE_FORMAT(TimeIn, '%Y-%m') = '2016-02' 
    OR DATE_FORMAT(TimeOut, '%Y-%m') = '2016-02' 
    OR (DATE_FORMAT(TimeIn, '%Y-%m') < '2016-02' AND TimeOut IS NULL) 
GROUP BY UserId; 
İlgili konular