【问题标题】:TSQL: how to select the client status in the date2 closest to date1 (date1 can be either much else less date2)TSQL:如何在最接近 date1 的 date2 中选择客户端状态(date1 可以比 date2 少得多)
【发布时间】:2019-11-26 11:09:32
【问题描述】:

假设,我们有一个客户表:

client  acctraction_dt  status     status_dt    date_diff
a       21.05.2019      big        13.05.2019   8
a       21.05.2019      small      22.05.2019   -1
a       21.05.2019      medium     25.05.2019   -4
b       01.04.2019      big        13.05.2019   -42
b       01.04.2019      small      22.05.2019   -51
b       01.04.2019      medium     25.05.2019   -54
c       01.06.2019      big        13.05.2019   19
c       01.06.2019      small      22.05.2019   10
c       01.06.2019      medium     25.05.2019   7

我想通过以下逻辑来定义,一个客户在吸引之日在公司处于什么状态:

a) 如果某些客户的 date_diff 0,我们应该从我们拥有的负数日期中取 max(date_diff),即除正数外最接近吸引日期的日期。

b) 如果某个客户的 min(date_diff)

c) 如果某个客户的 min(date_diff) > 0,则应该从我们拥有的日期中取 min(date_diff),即最接近景点日期的日期。

理想的结果是:

client a - small 因为 min(date_diff) 是负数。最小日期(-1 和 -4)之间的最大日期为 -1

client b - big 因为 min(date_diff) 是负数。日期之间的最大日期(-42、-51、-54)是-42

client c - medium 因为 min(date_diff) 是正数。日期(7、10、19)之间的最小日期为 7

我多次尝试使用 min、max 和 over ... 分区,但卡住了。

非常感谢您的帮助。

【问题讨论】:

  • 为什么“状态”列不够好,无法知道状态?什么公司”?期望的结果会有所帮助。

标签: sql sql-server tsql


【解决方案1】:

重写条件以使其更易于阅读:

  • 如果客户的最小值date_diff 为正值,我们将采用date_diff 值。
  • 任何其他情况中,我们将采用date_diff 值,该值在该客户端的负值中最接近于零。

所以这是一种可能的查询:

SELECT c.Client, 
CASE WHEN (SELECT MIN(date_diff) FROM Clients WHERE client = c.client) > 0
    THEN (SELECT MIN(date_diff) FROM Clients WHERE client = c.client)
    ELSE (SELECT TOP 1 date_diff FROM Clients WHERE client = c.client
            AND date_diff <= 0 ORDER BY date_diff DESC)
END AS AttractionStatus
FROM Clients c

【讨论】:

    【解决方案2】:

    您可以使用CTE 生成每个客户端的最小和最大日期差异,以及最大负日期差异,然后JOIN CTE 回到clients 表以获取客户端状态使用您提供的算法:

    WITH CTE AS (
      SELECT client, 
             MIN(date_diff) AS min_diff, 
             MAX(date_diff) AS max_diff,
             MAX(CASE WHEN date_diff < 0 THEN date_diff END) AS max_neg
      FROM clients
      GROUP BY client
    )
    SELECT c.client,
           c.status
    FROM CTE
    JOIN clients c ON c.client = CTE.client AND c.date_diff =
      CASE WHEN CTE.min_diff < 0 AND CTE.max_diff > 0 THEN CTE.max_neg
           WHEN CTE.min_diff <= 0 THEN CTE.max_diff
           ELSE CTE.min_diff
      END
    

    输出:

    client  status
    a       small
    b       big
    c       medium
    

    Demo on SQLFiddle

    【讨论】:

    • 尼克,非常感谢。我在真实数据上尝试了您的代码,并看到了许多重复的客户端及其状态(实际上:len(dataset)* len(dataset))。是什么原因造成的?
    • @AlexIvanov 抱歉——样本数据太小了,我没有注意到我在client 上遗漏了所需的JOIN 条件。我已经更新了答案和演示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多