【问题标题】:Function that returns MAX OR MIN dates based on ID count根据 ID 计数返回 MAX OR MIN 日期的函数
【发布时间】:2022-01-20 06:04:01
【问题描述】:

我在 SQL Server 中有一个任务,我需要使用 ID、PRODUCT_ID 和 DATE 列返回 RESULT_DATE 列。任务标准:

  1. 如果为每个 PRODUCT_ID 填写一次 DATE 列,那么我需要返回唯一的日期(例如 PRODUCT_ID 1 和 3)。假设它的 MIN 日期。

  2. 如果 DATE 列被填充了多次(例如 PRODUCT_ID 2),那么我需要返回下一个填充的 DATE 行。

数据:

CREATE TABLE #temp (
    ID INT,
    PRODUCT_ID INT,
    [DATE] DATETIME
    )
INSERT #temp (ID, PRODUCT_ID, DATE) VALUES 
(1, 1,  '2008-04-24 00:00:00.000'),
(2, 1,  NULL),
(3, 2,  '2015-12-09 00:00:00.000'),
(4, 2,  NULL),
(5, 2,  NULL),
(6, 2,  '2022-01-01 13:06:45.253'),
(7, 2,  NULL),
(8, 2,  '2022-01-19 13:06:45.253'),
(9, 3,  '2018-04-25 00:00:00.000'),
(10,3,  NULL),
(11,3,  NULL)
ID PRODUCT_ID DATE RESULT_DATE
1 1 2008-04-24 00:00:00.000 2008-04-24 00:00:00.000
2 1 NULL 2008-04-24 00:00:00.000
3 2 2015-12-09 00:00:00.000 2022-01-01 13:06:45.253
4 2 NULL 2022-01-01 13:06:45.253
5 2 NULL 2022-01-01 13:06:45.253
6 2 2022-01-01 13:06:45.253 2022-01-19 13:06:45.253
7 2 NULL 2022-01-19 13:06:45.253
8 2 2022-01-19 13:06:45.253 2022-01-19 13:06:45.253
9 3 2018-04-25 00:00:00.000 2018-04-25 00:00:00.000
10 3 NULL 2018-04-25 00:00:00.000
11 3 NULL 2018-04-25 00:00:00.000

我尝试了不同的技术,例如使用LEADLAG SQL 函数组合。最新的脚本:(但是还是不行)

SELECT 
COALESCE(DATE,
        CAST(
            SUBSTRING(
                MAX(CAST(DATE AS BINARY(4)) + CAST(DATE AS BINARY(4))) OVER ( PARTITION BY PRODUCT_ID ORDER BY DATE ROWS UNBOUNDED PRECEDING)
            ,5,4) 
        AS INT)
    ) AS RESULT_DATE,
*
FROM TABLE

【问题讨论】:

  • 为什么要将 [Date] 列转换为二进制,然后再转换为子字符串,然后再转换回日期?请不要使用保留字 (Date) 作为列名或表名 (TABLE)。我不确定你的代码是否真的运行。
  • 如果您以 DDL+DML 的形式提供示例数据,您可以更轻松地为人们提供帮助。
  • 你好@SteveFord。将 DATE 列名放在 [ ] 中就可以了。但是,代码没有如前所述正常运行。
  • @KonstantinsKovalovs 我知道您可以使用 [] 来转义这些保留字,但它确实使您的代码更难阅读和理解,因此仍然不应该使用保留字。为什么要将日期转换为二进制并将其添加到自身然后转换为 INT 然后在 COALESCE 中使用它根本没有意义。正如 Dale K 提到的,请添加 CREATE TABLE 语句、一些插入以插入测试数据、您正在尝试的查询、您收到的任何错误以及您的预期结果。
  • @SteveFord 我添加了脚本!预期结果在 RESULTS_DATA 列中可见:)

标签: sql sql-server tsql partition dense-rank


【解决方案1】:

您可以使用 CTE,选择具有非 NULL 日期的所有行,给每个行一个 row_number,然后使用第二个 CTE 从第一个 CTE 中获取所有行,该日期等于每个 product_id 的最大行号小于的日期比 3. 最后将此 CTE 加入到原始表中,为每一行提供第二个日期:

设置

CREATE TABLE #temp (
    ID INT,
    PRODUCT_ID INT,
    MyDATE DATETIME
)
INSERT #temp (ID, PRODUCT_ID, MyDate) 
VALUES 
    (1, 1,  '2008-04-24 00:00:00.000'),
    (2, 1,  NULL),
    (3, 2,  '2015-12-09 00:00:00.000'),
    (4, 2,  NULL),
    (5, 2,  NULL),
    (6, 2,  '2022-01-01 13:06:45.253'),
    (7, 2,  NULL),
    (8, 2,  '2022-01-19 13:06:45.253'),
    (9, 3,  '2018-04-25 00:00:00.000'),
    (10,3,  NULL),
    (11,3,  NULL);

查询:

;WITH CTE
AS
(
    SELECT ID, Product_ID, MyDate, 
        ROW_NUMBER() OVER (PARTITION BY Product_ID ORDER BY Id) AS rn
    from #temp
    WHERE MyDate IS NOT NULL
),
CTE2
AS
(
    SELECT *
    FROM CTE C1
    WHERE C1.rn < 3 
        AND
        C1.rn = 
            (SELECT MAX(rn) FROM CTE WHERE Product_Id = C1.Product_Id AND rn<3)
)
SELECT T.Id, T.Product_Id, T.MyDate, C.MyDate As Result_date
FROM #temp T
INNER JOIN CTE2 C
    ON T.Product_Id = C.Product_Id
ORDER BY T.Id;

结果:

Id  Product_Id  MyDate                   Result_Date
1   1           2008-04-24 00:00:00.000  2008-04-24 00:00:00.000
2   1           NULL                     2008-04-24 00:00:00.000
3   2           2015-12-09 00:00:00.000  2022-01-01 13:06:45.253
4   2           NULL                     2022-01-01 13:06:45.253
5   2           NULL                     2022-01-01 13:06:45.253
6   2           2022-01-01 13:06:45.253  2022-01-01 13:06:45.253
7   2           NULL                     2022-01-01 13:06:45.253
8   2           2022-01-19 13:06:45.253  2022-01-01 13:06:45.253
9   3           2018-04-25 00:00:00.000  2018-04-25 00:00:00.000
10  3           NULL                     2018-04-25 00:00:00.000
11  3           NULL                     2018-04-25 00:00:00.000

【讨论】:

  • 感谢您的回答,但与结果示例中的不太一样。 Product_id Resul_Date 列 Product_Id 应为:3 2022-01-01 13:06:45.253 4 2022-01-01 13:06:45.253 5 2022-01-01 13:06:45.253 6 2022-01-19 13:06:45.253 7 2022-01-19 13:06:45.253 8 2022-01-19 13:06:45.253
  • @KonstantinsKovalovs 结果与问题中显示的结果完全匹配,我已重新格式化结果以使其更清晰。它们也与您的 cmets 相匹配,所以不确定您的意思
猜你喜欢
  • 2017-08-24
  • 1970-01-01
  • 2019-04-15
  • 2012-12-18
  • 2018-05-02
  • 2021-11-22
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
相关资源
最近更新 更多