需要查询才能显示员工付款日期。

时间:2014-01-06 10:00:21

标签: sql-server sql-server-2008 sql-server-2005 sql-server-2008-r2

我有一张这样的表:

EMP:

EMPNO   ENAME   JOB         MGR     HIREDATE    SAL     COMM    DEPTNO
7934    MILLER  CLERK       7782    01/23/1982  1300     -      10
7369    SMITH   CLERK       7902    12/17/1980  800      -      20
7521    WARD    SALESMAN    7698    02/22/1981  1250    500     30
7654    MARTIN  SALESMAN    7698    09/28/1981  1250    1400    30
7698    BLAKE   MANAGER     7839    05/01/1981  2850     -      30
7782    CLARK   MANAGER     7839    06/09/1981  2450     -      10
7839    KING    PRESIDENT    -      11/17/1981  5000     -      10
7844    TURNER  SALESMAN    7698    09/08/1981  1500     -      30
7499    ALLEN   SALESMAN    7698    02/20/1981  1600    300     30
7566    JONES   MANAGER     7839    04/02/1981  2975     -      20
7788    SCOTT   ANALYST     7566    12/09/1982  3000     -      20
7876    ADAMS   CLERK       7788    01/12/1983  1100     -      20
7900    JAMES   CLERK       7698    12/03/1981  950      -      30
7902    FORD    ANALYST     7566    12/03/1981  3000     -      20

如果在该月的最后一个星期五支付任何月份的15日或之前雇用的Emp,那么在15日之后雇用的人将在下个月的第一个星期五付款。打印一份emps列表及其雇用日期和支付日期。

在oracle中我们可以通过简单的查询实现这一点。任何人都可以建议我使用简单的SQL Server查询来显示所需的结果。

以下是我在SQL server中尝试过的代码,

SELECT *,CASE WHEN DATEPART(DD,HIREDATE)<=15 
            THEN (CASE WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))='MONDAY' 
            THEN DATEADD(DD,-4,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))='TUESDAY'
            THEN DATEADD(DD,-3,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))='WEDNESDAY'
            THEN DATEADD(DD,-5,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))='THURSDAY'
            THEN DATEADD(DD,-6,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))='FRIDAY'
            THEN DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))='SATURDAY'
            THEN DATEADD(DD,-1,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))='SUNDAY'
            THEN DATEADD(DD,-2,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))),DATEADD(mm,1,HIREDATE))))
            END)
    ELSE CASE
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))='MONDAY'
            THEN DATEADD(DD,2,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))='TUESDAY'
            THEN DATEADD(DD,4,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))='WEDNESDAY'
            THEN DATEADD(DD,3,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))='THURSDAY'
            THEN DATEADD(DD,1,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))='FRIDAY'
            THEN DATEADD(DD,0,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))='SATURDAY'
            THEN DATEADD(DD,6,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))
            WHEN DATENAME(WEEKDAY,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))='SUNDAY'
            THEN DATEADD(DD,5,(DATEADD(dd,-(DAY(DATEADD(mm,1,HIREDATE))-1),DATEADD(mm,1,HIREDATE))))
        END
    END
FROM EMP;

上面的查询正在按预期工作,但我正在寻找一种简单的方法来实现这一点..... :)

4 个答案:

答案 0 :(得分:0)

不知道你想要的结果,这应该足以让你前进。 CASEDAY TSQL语句将帮助您实现目标。

SELECT
    [EmpNo], 
    [EName], 
    [HireDate], 
    CASE 
        WHEN DAY([HireDate]) <= 15 THEN 'Last Friday'
        ELSE 'First Friday' 
    END AS 'PayDate'
FROM EMP

答案 1 :(得分:0)

这不是你在SQL Server中可以做的事情。如果您确信疯了,请查看使用各种dateadddatediff%操作的this example

稍微好一点的选择是像C#这样的客户端语言,请参阅this SO answer。还是在理智的另一面。

在一天结束时,在Oracle中完成工资核算更容易。您可以使用next_day()

select  next_day(trunc(sysdate,'MM'), 'FRIDAY') as first_friday
,       next_day(last_day(sysdate)-7, 'FRIDAY') as last_friday
from    dual

这仍然不是那么容易,但比你在T-SQL中做的任何事情都容易。

答案 2 :(得分:0)

创建功能

CREATE FUNCTION fn_FirstLastFriday(@Year INT)
RETURNS  TABLE 
AS 
-- First and Last Friday
RETURN 
(select min(dates) as [First Friday], max(dates) as [Last Friday] from
(
select dateadd(day,number-1,DATEADD(year,@year-1900,0))
as dates from master..spt_values
where type='p' and number between 1 and
DATEDIFF(day,DATEADD(year,@year-1900,0),DATEADD(year,@year-1900+1,0))
) as t
where DATENAME(weekday,dates)='friday'
group by DATEADD(month,datediff(month,0,dates),0))

测试表

DECLARE @EMP TABLE (EMPNO INT,ENAME VARCHAR(20),JOB VARCHAR(20)
               ,MGR INT, HIREDATE DATE, SAL INT,COMM INT, DEPTNO INT)
INSERT INTO @EMP
VALUES
(7934,'MILLER','CLERK',7782,'01/23/1982',1300, NULL,10),
(7369,'SMITH','CLERK',7902,'12/17/1980',800,NULL,20),
(7521,'WARD','SALESMAN',7698,'02/22/1981',1250,500,30)

<强>查询

SELECT *, CASE WHEN DAY(E.HIREDATE) >= 1 AND DAY(E.HIREDATE) <= 15 THEN T.[Last Friday]
                ELSE T.[First Friday] END AS Friday
FROM @EMP E
       CROSS APPLY 
               dbo.fn_FirstLastFriday(YEAR(E.HIREDATE)) T

结果集

╔═══════╦════════╦═══════╦══════╦════════════╦══════╦══════╦════════╦═════════════════════════╦═════════════════════════╦═════════════════════════╗
║ EMPNO ║ ENAME  ║  JOB  ║ MGR  ║  HIREDATE  ║ SAL  ║ COMM ║ DEPTNO ║      First Friday       ║       Last Friday       ║         Friday          ║
╠═══════╬════════╬═══════╬══════╬════════════╬══════╬══════╬════════╬═════════════════════════╬═════════════════════════╬═════════════════════════╣
║  7934 ║ MILLER ║ CLERK ║ 7782 ║ 1982-01-23 ║ 1300 ║ NULL ║     10 ║ 1982-01-01 00:00:00.000 ║ 1982-01-29 00:00:00.000 ║ 1982-01-01 00:00:00.000 ║
║  7934 ║ MILLER ║ CLERK ║ 7782 ║ 1982-01-23 ║ 1300 ║ NULL ║     10 ║ 1982-02-05 00:00:00.000 ║ 1982-02-26 00:00:00.000 ║ 1982-02-05 00:00:00.000 ║
║  7934 ║ MILLER ║ CLERK ║ 7782 ║ 1982-01-23 ║ 1300 ║ NULL ║     10 ║ 1982-03-05 00:00:00.000 ║ 1982-03-26 00:00:00.000 ║ 1982-03-05 00:00:00.000 ║
║  7934 ║ MILLER ║ CLERK ║ 7782 ║ 1982-01-23 ║ 1300 ║ NULL ║     10 ║ 1982-04-02 00:00:00.000 ║ 1982-04-30 00:00:00.000 ║ 1982-04-02 00:00:00.000 ║
║  7934 ║ MILLER ║ CLERK ║ 7782 ║ 1982-01-23 ║ 1300 ║ NULL ║     10 ║ 1982-05-07 00:00:00.000 ║ 1982-05-28 00:00:00.000 ║ 1982-05-07 00:00:00.000 ║
║  7934 ║ MILLER ║ CLERK ║ 7782 ║ 1982-01-23 ║ 1300 ║ NULL ║     10 ║ 1982-06-04 00:00:00.000 ║ 1982-06-25 00:00:00.000 ║ 1982-06-04 00:00:00.000 ║
╚═══════╩════════╩═══════╩══════╩════════════╩══════╩══════╩════════╩═════════════════════════╩═════════════════════════╩═════════════════════════╝

注意

  

我已经添加了第一个和最后一个星期五在我的答案中只有Demo   pupose,但您可以从答案中排除这些列   使用我使用CASE语句的最后一列[星期五]。

答案 3 :(得分:0)

 SELECT ENAME, HIREDATE,
 CASE WHEN TO_CHAR(HIREDATE,'DD')<=15 
 THEN NEXT_DAY(LAST_DAY(HIREDATE)-7,'FRI')
 ELSE NEXT_DAY(LAST_DAY(ADD_months(HIREDATE,1))-7,'FRI')
 END "payDATE"
 FROM EMP;