You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle中为多日期行ID创建透视表 并筛选仅含2015年前日期的ID

问题与解决方案

问题背景

现有一张包含ID和Date列的表,同一ID对应多行数据,每行仅含一个日期值。原始数据如下:

ID   Date
1    01/01/2015
1    02/01/2015
1    03/01/2014
2    01/01/2014
3    02/01/2015
3    01/01/2014

期望生成如下格式的透视表(将同一ID的日期横向展开):

ID   DATE         DATE        DATE
1    01/01/2015   02/01/2015  03/01/2014
2    01/01/2014   NULL        NULL
3    02/01/2015   01/01/2014  NULL

最终核心需求:找出所有关联日期都早于2015年的ID。直接使用WHERE Date < '2015-01-01'筛选无效,因为这类筛选会保留那些同时存在2015及以后日期的ID的旧日期行,不符合需求。


一、生成透视表

透视表的实现依赖具体SQL方言,以下是主流数据库的实现方式:

1. SQL Server(使用PIVOT语法)

先为每个ID的日期生成序号,再通过PIVOT横向展开:

WITH RankedDates AS (
    SELECT 
        ID,
        Date,
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date DESC) AS DateRank
    FROM YourTableName
)
SELECT 
    ID,
    [1] AS DATE_1,
    [2] AS DATE_2,
    [3] AS DATE_3
    -- 可根据实际最大日期行数增加更多列
FROM RankedDates
PIVOT (
    MAX(Date) FOR DateRank IN ([1], [2], [3])
) AS PivotTable;

2. MySQL(条件聚合实现)

MySQL无原生PIVOT,用条件聚合模拟:

SELECT
    ID,
    MAX(CASE WHEN DateRank = 1 THEN Date END) AS DATE_1,
    MAX(CASE WHEN DateRank = 2 THEN Date END) AS DATE_2,
    MAX(CASE WHEN DateRank = 3 THEN Date END) AS DATE_3
FROM (
    SELECT
        ID,
        Date,
        @rank := IF(@prev_id = ID, @rank + 1, 1) AS DateRank,
        @prev_id := ID
    FROM YourTableName, (SELECT @rank := 0, @prev_id := NULL) AS vars
    ORDER BY ID, Date DESC
) AS RankedDates
GROUP BY ID;

3. PostgreSQL(条件聚合实现)

SELECT
    ID,
    MAX(CASE WHEN DateRank = 1 THEN Date END) AS DATE_1,
    MAX(CASE WHEN DateRank = 2 THEN Date END) AS DATE_2,
    MAX(CASE WHEN DateRank = 3 THEN Date END) AS DATE_3
FROM (
    SELECT
        ID,
        Date,
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date DESC) AS DateRank
    FROM YourTableName
) AS RankedDates
GROUP BY ID;

二、筛选仅含2015年前日期的ID

以下两种方法均可准确实现需求:

方法1:使用NOT EXISTS

通过子查询检查当前ID是否存在2015及以后的日期,仅保留无此类日期的ID:

SELECT DISTINCT ID
FROM YourTableName t1
WHERE NOT EXISTS (
    SELECT 1
    FROM YourTableName t2
    WHERE t2.ID = t1.ID
    AND t2.Date >= '2015-01-01'
);

方法2:使用GROUP BY + HAVING

通过分组后检查ID的最大日期是否早于2015年:

SELECT ID
FROM YourTableName
GROUP BY ID
HAVING MAX(Date) < '2015-01-01';

这两种方法均会返回仅包含2015年之前日期的ID(示例中为ID=2)。


内容的提问来源于stack exchange,提问作者CHarrison

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 11:15:43