【问题标题】:Need a query to display employee payment date.?需要查询以显示员工付款日期。?
【发布时间】:2014-01-23 16:54:21
【问题描述】:

我有一张这样的桌子:

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 日或之前雇用的员工在该月的最后一个星期五支付工资,那么在 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;

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

【问题讨论】:

  • 在获得任何帮助之前,我们需要先看看您首先尝试了什么。
  • 嗨@RaduGheorghiu 查看我的查询

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


【解决方案1】:
 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;

【讨论】:

    【解决方案2】:

    创建一个函数

    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 ║
    ╚═══════╩════════╩═══════╩══════╩════════════╩══════╩══════╩════════╩═════════════════════════╩═════════════════════════╩═════════════════════════╝
    

    注意

    我在我的回答中添加了第一个和上周五 目的,但是您可以从答案中排除这些列,并且仅 使用我使用了CASE 语句的最后一列 [Friday]。

    【讨论】:

      【解决方案3】:

      这不是您可以在 SQL Server 中正常执行的操作。如果你没问题,请查看this example,它使用各种dateadddatediff% 操作。

      更好的选择是 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 中可以做的任何事情都容易。

      【讨论】:

        【解决方案4】:

        在不知道您想要的结果的情况下,这应该足以让您继续前进。 CASEDAY TSQL 语句将帮助您实现结果。

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

        【讨论】:

        • 我们应该根据hiredate并使用他们提到的标准来显示PayDate。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-01-15
        • 2022-07-12
        • 2015-10-18
        • 2019-08-25
        • 2016-01-05
        • 2013-12-18
        • 2021-08-17
        相关资源
        最近更新 更多