2012-04-02 5 views
0

Hallo wieder SQL Server 2008-Gurus.SQL Server 2008 CASE-Logik in SELECT-Anweisung

Ich muss die folgenden Regeln für die Einstellung der Anfangs- und Endzeiten eines Mitarbeiters für seinen Arbeitstag (stündliche Mitarbeiter) in einer SELECT-Anweisung anwenden. Ich entschuldige mich im Voraus für meine SQL-Ignoranz.

  1. Die Regel ist ihre Startzeit auf einen Wert in einem Tabellenfeld für die Arbeiter gespeichert setzen, wenn sie am oder vor ihrer Startzeit anmelden (eine in den Arbeitern starttime Spalte gespeichert Zeit) und damit Kredit für den Start zu ihrer Startzeit.

    Wenn sie sich innerhalb von 10 Minuten vor oder nach ihrer Endzeit in einer Spalte für den Arbeiter abmelden, erhalten sie den vollen Tag, ein anderer Wert wird in einer Spalte der Arbeitertabelle gespeichert, ansonsten sind sie bestraft einige Prozent einer Stunde, dh ihre Abmeldung Zeit gerundet auf .25 einer Stunde weniger am nächsten zu der Zeit, die sie ausgeloggt. d.h. wenn sie sich um 4:30 abmeldet und sie sich um 4:18 abmeldet, ist ihre Abmeldezeit 4:15. Wenn sie sich um 4:20 abmelden und um 4:30 abmelden, ist ihre Abmeldezeit 4:30.

  2. Die erste Regel gilt für alle Stundenarbeiter, deren Arbeitsstunden weniger oder gleich ihrem erwarteten Arbeitstag sind. Der Vorbehalt gilt für diejenigen, bei denen Überstunden in Ordnung sind (ein Bitwert ist auf 1 gesetzt). Wenn Überstunden erlaubt sind, kann die Anzahl der abzurechnenden Stunden den für sie gespeicherten Wert für den ganzen Tag übersteigen, und daher kann der Wert ihrer Abmeldezeit den Gesamtwert überschreiten.

    Die Frage ist, können diese Regeln in der SELECT-Anweisung berechnet werden, und wenn ja, kann ich Hilfe mit dem Code bekommen?

Die Spalten, die Informationen enthalten, sind:

worker.startime (TIME) 
    worker.endtime (TIME) 
    worker.overtimeallowed (BIT) 
    worker.workdayhours (decimal (12,2)) 
    worker.penaltyvalue (decimal (12,2)) 

Wenn es eine UDF oder gespeicherte Prozedur erfordert (da ich die Telerik Report bin mit) Ich bin nicht sicher, würde es unterstützt werden, aber Das ist wahrscheinlich eine andere Frage.

Bisher habe ich Hilfe bei der Anwendung einiger CASE-Logik bekommen - Berechnung, ob ein Arbeiter für sein 1/2 Mittagessen Kredit bekommt. Der Code, der geliefert wurde, funktioniert wie versprochen. Dies, glaube ich, kann eine Verlängerung dieser Logik sein - so werde ich den Code zur Verfügung stellen Ich habe hier:

 -- for testing purposes only. 
     DECLARE @StartDate AS DateTime 
     SET @StartDate = CAST('03/25/2012' AS DATE) 
     DECLARE @EndDate AS DateTime 
     SET @EndDate = CAST('04/10/2012' AS DATE) 

     SELECT 
     w.Firstname 
    ,w.Lastname 
    ,wf.Login 
    ,wf.logout 
    ,ROUND(CAST(DATEDIFF(MI, wf.Login, wf.Logout) AS DECIMAL)/60,2) 
    - CASE 
     WHEN DATEDIFF(hour, wf.Login, wf.Logout) < w.MinimumHours THEN  
      w.LunchDeduction 
     ELSE 
     0 
     END AS [Hours Credited] 
    FROM Workers AS w 
    JOIN Workflow AS wf 
    ON wf.LoggedInWorkerid = w.ID 
    JOIN Roles AS r 
    ON w.RoleID = r.RoleID 
    WHERE (r.Descript = 'Hourly') 
    AND wf.Login >= @StartDate AND wf.Logout <= @EndDate 
    ORDER BY w.Lastname, w.Firstname 
+0

Ja, es klingt wie alles in einer Abfrage getan werden kann. Wie die meisten Probleme, versuche es zu brechen.Cut'n'paste dein vorhandenes 'CASE' und modifiziere es, um die" 10 Minuten "Regel zu überprüfen und ein Flag auszugeben. Fügen Sie dann jeweils eine Ebene hinzu. Du wirst es bald genug haben. – HABO

+0

In den meisten Jurisdiktionen, wenn ein Mitarbeiter früh eincheckt, müssen Sie diese für die Zeit bezahlen, auch wenn Überstunden nicht genehmigt werden. Sie haben gearbeitet, sie werden bezahlt. Zeitraum. Ja, es ist ein Problem, aber niemand, mit dem Sie umgehen, indem Sie das Gehalt zurückhalten. HR hat ein Gespräch mit dem Manager über die Festlegung von Erwartungen, und der Manager hat mit dem Angestellten ein Gespräch darüber, wann sie auftauchen und einchecken; Wenn die Erwartungen immer noch nicht erfüllt sind, beginnt das Management mit dem Disziplinarverfahren, um die Einhaltung durchzusetzen. Aber wenn sie einsteigen und arbeiten, werden sie bezahlt. –

Antwort

0

Hier ist ein Beispiel mit Einschränkungen wählen Umgang Sie beschrieben. CTEs erstellen Tabellen für Testzwecke. Die Hauptabfrage zeigt die Berechnungen an. Du hast mit Da- tiffen und Datumsangaben gearbeitet, also gibt es kein Geheimnis. Wenn Sie% noch nicht verwenden, wird modulo operator verwendet, um die Zeit auf 15 Minuten zu runden.

;with worker (ID, overtime, startTime, endTime) as 
(
    select 1, 1, CAST ('08:30' as time), CAST ('16:30' as time) 
    union all 
    select 2, 0, CAST ('08:30' as time), CAST ('16:30' as time) 
    union all 
    select 3, 0, CAST ('08:30' as time), CAST ('16:30' as time) 
), 
-- Test table of workflows 
wf (workerID, login, logout) as 
(
    select 1, CAST ('2012-03-11 08:20' as datetime), CAST ('2012-03-11 19:33' as datetime) 
    union all 
    select 2, CAST ('2012-03-11 08:50' as datetime), CAST ('2012-03-11 16:20' as datetime) 
    union all 
    select 3, CAST ('2012-03-11 08:22' as datetime), CAST ('2012-03-11 16:18' as datetime) 
) 
select wf.workerID, 
    wf.login, 
    wf.logout, 
    -- if starttime > login return startTime else login 
    case when DATEDIFF(MI, w.startTime, cast (wf.login as time)) < 0 
    then cast(CAST (wf.login AS date) AS datetime) + w.startTime 
    else wf.login 
    end roundedLogin, 
    case when w.overtime = 1 -- Round to 15 minutes whenever finished 
     OR 
     -- Round to 15 minutes if left ten or more minutes before endTime 
      DATEDIFF(MI, cast (wf.logout as time), dateadd (MI, -10, w.endTime)) > 0 
    then dateadd (MI, -(DATEPART (MI, wf.logout) % 15), wf.logout) 
    -- stop at endTime if overtime = 0 OR left job at apropriate time 
    else cast(CAST (wf.logout AS date) AS datetime) + w.endTime 
    end roundedLogout 
from worker w 
    inner join wf 
    on w.ID = wf.workerID 

Es wird ein Problem mit diesem Ansatz geben. Wenn Sie beginnen, Mathematik in die ursprüngliche Abfrage zu integrieren, werden Sie feststellen, dass Sie Ausdrücke schreiben müssen, die gerundetesLogin und gerundetesLogout erneut berechnen, um abrechenbare Stunden zu berechnen. Sie können den im selben Bereich definierten Alias ​​nicht erneut verwenden, aber Sie können abgeleitete Tabellen- oder Sichtfelder oder sogar berechnete Felder erstellen. Anzeigen von wiederkehrenden Spalten aus Workflows und allen zusätzlichen Ausdrücken wäre wahrscheinlich die beste.

Die Verwendung dieser Ansicht in anderen Abfragen würde die Vorgänge vereinfachen, indem die Logik an einer Stelle gekapselt wird.

+0

Ich mag diese Antwort Nikola. Ich habe ein gespeichertes Proc zusammengestellt, aber es hat diese Logik nicht. Ich kann nicht den Code eingeben, den ich mit deinem zusammengebaut habe, also muss ich wohl eine andere Frage stellen. Mit der Macht eines gespeicherten Procs hinter dem Bericht - ich nehme an, dass ich ein DATEDIFF auf dem abgerundeten Login und dem gerundeten Abmelden bekommen kann, was wunderbar wäre. –

+0

Ja, Sie können, aber im Moment müssen Sie Ausdrücke jedes Mal wiederholen, wenn Sie es verwenden, sogar in derselben Abfrage. Daher ein Vorschlag zum Erstellen einer Sicht auf Workflow mit diesen zwei Spalten hinzugefügt. –

+0

Ich spiele schon eine Weile damit und versuche es herauszufinden. Warum sollte der wf.logout Wert von 2012-03-05 19: 20: 45.000 in roundLogout auf 1900-01-01 16: 30: 00.000 mit Ihrem -> CASE WHEN w.OvertimeOk = 1 OR DATEDIFF (MI, wf.logout, dateadd (MI, 10, w.endTime))> 0 DANN dateadd (MI, - (DATEPART (MI, wf.logout)% 15), wf.logout) <- wenn w.OvertimeOk = 0 ? Dies ist der Wert, der für jeden Datensatz gesetzt wird, in dem w.OvertimeOk = 0 ist, aber er funktioniert perfekt, wenn er eine OvertimeOk = 1 trifft. –