【问题标题】:Compare 3 Consecutive rows in a table比较表中的 3 个连续行
【发布时间】:2012-10-17 05:10:32
【问题描述】:

您好,我有一个有趣的问题。我有一个员工表如下

CREATE TABLE EMPLOYEE(
EMPLOYEE_ID INTEGER,
SALARY DECIMAL(18,2),
PAY_PERIOD DATE)

现在这些表格中有员工,其中一些人按月、一些每周、一些双周和一些每天获得报酬。如果三个连续支付周期的工资相等,我们想要找到一个指标为“Y”。让我们举个例子。

Employee   Pay_Period     Salary

  1         01/01/2012    $500
  1         08/01/2012    $200
  1         15/01/2012    $200
  1         22/01/2012    $200
  1         29/01/2012    $700

在这种情况下,指标应为“是”,因为连续 3 个支付期的工资为 200 美元。

由于支付周期的数量不是恒定的,我不确定如何编写此代码,因为我事先不知道我需要多少左联接。由于我在 Teradata 中编写此代码,因此我尝试使用 RECURSIVE 函数但被难住了。关于如何进行此操作的任何一般想法?我宁愿不创建存储过程或使用 PL/SQL 逻辑。

【问题讨论】:

  • 在 Oracle 中这将是一个 LAG 函数
  • 在 Oracle 中,您根本不会得到报酬。这是 Larry() 函数。

标签: sql teradata


【解决方案1】:

Teradata 可能不像 Oracle 和 SQL Server 现在支持的那样支持 LEAD 和 LAG,但这些功能的前提是为您的窗口聚合函数选择正确的窗口。在 Teradata 中,可以通过在窗口聚合函数中使用 ROWS BETWEEN 子句来完成 LEAD 和 LAG。

以下是您如何使用 ROWS BETWEEN 和在牌桌上的单次通过来完成您想要做的事情:

CREATE VOLATILE TABLE myTable
( myID SMALLINT NOT NULL,
  PayPeriod DATE NOT NULL,
  PayAmount DECIMAL(5,2) NOT NULL)
PRIMARY INDEX (myID) 
ON COMMIT PRESERVE ROWS;

INSERT INTO myTable VALUES (1, DATE '2012-01-01', 500);
INSERT INTO myTable VALUES (1, DATE '2012-01-08', 200);
INSERT INTO myTable VALUES (1, DATE '2012-01-15', 200);
INSERT INTO myTable VALUES (1, DATE '2012-01-22', 200);
INSERT INTO myTable VALUES (1, DATE '2012-01-29', 700);


SELECT myID
     , PayPeriod
     , PayAmount
     , MAX(PayAmount) OVER (PARTITION BY myID 
                                ORDER BY PayPeriod 
                            ROWS BETWEEN 1 FOLLOWING 
                                     AND 1 FOLLOWING) AS NextPayAmount_
     , MAX(PayAmount) OVER (PARTITION BY myID 
                                ORDER BY PayPeriod 
                            ROWS BETWEEN 2 FOLLOWING 
                                     AND 2 FOLLOWING) AS NextPayAmount2_
     , CASE WHEN NextPayAmount_ = PayAmount
             AND NextPayAmount2_ = PayAmount
            THEN 'Y'
            ELSE 'N'
       END PayIndicator_
  FROM myTable;

结果

1   2012-01-01  500 200 200 N
1   2012-01-08  200 200 200 Y
1   2012-01-15  200 200 700 N
1   2012-01-22  200 700   ? N
1   2012-01-29  700   ?   ? N

【讨论】:

  • 我喜欢这个解决方案。非常感谢。这非常有用!
【解决方案2】:

Teradata 没有领先/落后。但是,它确实有row_number()。所以,你可以做你想做的事:

with  as (
    select e.*,
           row_number() over (partition by employee_id order by pay_period) as seqnum
    from employee
)
select <whatever you want>
from emp e join
     emp e1 join
     on e.employee_id = e1.employee_id and
        e.seqnum = e1.seqnum+1
     emp e2
     on e.employee_id = e2.employee_id and
        e.seqnum = e2.seqnum+2
where e.salary = e1.salary and e.salary = e2.salary

除此之外,我确实有一些建议。首先,您的employee 表应该有每个员工一行,主键为employee_id。这个表应该叫做EmployeeSalary。其次,您的支付周期应该有两个日期,一个开始日期和一个结束日期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 2015-08-19
    • 1970-01-01
    相关资源
    最近更新 更多