无法在 sql 中正确使用滞后功能
Unable to use lag function correctly in sql
我从多个 table 创建了一个 table,如下所示:
Week | Cid | CustId | L1
10 | 1 | 1 | 2
10 | 2 | 1 | 2
10 | 5 | 1 | 2
10 | 4 | 1 | 1
10 | 3 | 2 | 1
4 | 6 | 1 | 2
4 | 7 | 1 | 2
我希望输出为:
Repeat
0
1
1
0
0
0
1
所以,基本上我想要的是每个星期,如果一个人(custid)再次以相同的 L1 进来,那么 Repeat
列中的值应该变为 1,否则为 0(就像,在这里,在第 2 行和第 3 行中,custid 1 再次出现 L1=2,因此它将在 "Repeat" 列中获得 1,但是在第 4 行中,custid 1 出现了 L1=1,因此它将获得值作为 ).
顺便说一句,table 没有排序(如我所示)。
我正在尝试按如下方式进行:
select t.*,
lag(0, 1, 0) over (partition by week, custid, L1 order by cid) as repeat
from
table;
但这并没有给出输出,而是给出了空结果。
我认为您需要 case
,但我会为此使用 row_number()
:
select t.*,
(case when row_number() over (partition by week, custid, l1 order by cid) = 1
then 0 else 1
end) as repeat
from table;
这也可以在没有 Window 函数的情况下进行计算,但可以通过以下方式进行自连接:
SELECT a.week, a.cid, a.custid, a.l1,
CASE WHEN b IS NULL THEN 1 ELSE 0 END AS repeat
FROM mytable a NATURAL LEFT JOIN
(SELECT week, min(cid) AS cid, custid, l1 FROM mytable
GROUP BY week,custid,l1) b
ORDER BY week DESC, custid, l1 DESC, cid;
它可以简单地通过使用 count(*) 作为解析函数来完成。不需要 case 表达式或自连接。该查询甚至可以跨支持分析功能的数据库移植:
SELECT cust.*, least(count(*)
OVER (PARTITION BY Week, CustId, L1 ORDER BY Cid
ROWS UNBOUNDED PRECEDING) - 1, 1) repeat
FROM cust ORDER BY Week DESC, custId, L1 DESC;
对您的数据执行查询会产生以下输出(最后一行是重复行):
Week | Cid | CustId | L1 | repeat
10 1 1 2 0
10 2 1 2 1
10 5 1 2 1
10 4 1 1 0
10 3 2 1 0
4 6 1 2 0
4 7 1 2 1
已在 Oracle 11g 和 PostgreSQL 9.4 上测试。请注意,第二个 ORDER BY
是可选的。有关详细信息,请参阅 Oracle Language Reference, Analytic Functions。
我从多个 table 创建了一个 table,如下所示:
Week | Cid | CustId | L1
10 | 1 | 1 | 2
10 | 2 | 1 | 2
10 | 5 | 1 | 2
10 | 4 | 1 | 1
10 | 3 | 2 | 1
4 | 6 | 1 | 2
4 | 7 | 1 | 2
我希望输出为:
Repeat
0
1
1
0
0
0
1
所以,基本上我想要的是每个星期,如果一个人(custid)再次以相同的 L1 进来,那么 Repeat
列中的值应该变为 1,否则为 0(就像,在这里,在第 2 行和第 3 行中,custid 1 再次出现 L1=2,因此它将在 "Repeat" 列中获得 1,但是在第 4 行中,custid 1 出现了 L1=1,因此它将获得值作为 ).
顺便说一句,table 没有排序(如我所示)。
我正在尝试按如下方式进行:
select t.*,
lag(0, 1, 0) over (partition by week, custid, L1 order by cid) as repeat
from
table;
但这并没有给出输出,而是给出了空结果。
我认为您需要 case
,但我会为此使用 row_number()
:
select t.*,
(case when row_number() over (partition by week, custid, l1 order by cid) = 1
then 0 else 1
end) as repeat
from table;
这也可以在没有 Window 函数的情况下进行计算,但可以通过以下方式进行自连接:
SELECT a.week, a.cid, a.custid, a.l1,
CASE WHEN b IS NULL THEN 1 ELSE 0 END AS repeat
FROM mytable a NATURAL LEFT JOIN
(SELECT week, min(cid) AS cid, custid, l1 FROM mytable
GROUP BY week,custid,l1) b
ORDER BY week DESC, custid, l1 DESC, cid;
它可以简单地通过使用 count(*) 作为解析函数来完成。不需要 case 表达式或自连接。该查询甚至可以跨支持分析功能的数据库移植:
SELECT cust.*, least(count(*)
OVER (PARTITION BY Week, CustId, L1 ORDER BY Cid
ROWS UNBOUNDED PRECEDING) - 1, 1) repeat
FROM cust ORDER BY Week DESC, custId, L1 DESC;
对您的数据执行查询会产生以下输出(最后一行是重复行):
Week | Cid | CustId | L1 | repeat
10 1 1 2 0
10 2 1 2 1
10 5 1 2 1
10 4 1 1 0
10 3 2 1 0
4 6 1 2 0
4 7 1 2 1
已在 Oracle 11g 和 PostgreSQL 9.4 上测试。请注意,第二个 ORDER BY
是可选的。有关详细信息,请参阅 Oracle Language Reference, Analytic Functions。