【问题标题】:Identifying users with a downward trend SQL识别具有下降趋势 SQL 的用户
【发布时间】:2021-10-20 18:26:23
【问题描述】:

试图找出数量比上次购买减少的客户列表。

在此示例中,我们看到,随着时间的推移,Mary 的数量随着每次新购买而减少。然而,尽管 Bob 显示下降,但他不会在结果中产生收益,因为在 9/19 他购买了 8 个数量,这比他之前购买的 5 个数量多。

我正试图为我的一生找出一个查询我似乎无法将它放在一起

Customer    PurchaseDate    Quantity
Bob         9/1/2021        10
Bob         9/10/2021       6
Bob         9/18/2021       5
Bob         9/19/2021       8
Mary        9/1/2021        10
Mary        9/10/2021       6
Mary        9/18/2021       5
Mary        9/19/2021       3
Frank       9/1/2021        5
Lucus       9/1/2021        5
Lucus       9/10/2021       6
Lucus       9/18/2021       10

最终结果应该是

Customer
Mary

【问题讨论】:

  • 什么是精确的 MySQL 版本?
  • 到目前为止你尝试过什么?你在哪里卡住了?
  • @akina 5.6.41-84.1
  • 您是否希望从某个特定时期(每月、每年、每季度等)确定趋势?趋势通常通过比较两点的总和来确定,以验证前一点与当前点。或者您只是想知道最近的数量是否少于之前的数量?
  • 正如我所提到的,趋势通常来自两个点的聚合,因为初始点是 100% 以建立基线。例如:对于年度趋势SUM(2018.quantity) / SUM(2017.quantity) * 100 将是年度趋势。如果小于100%,则向下,否则向上。

标签: mysql sql


【解决方案1】:

这有点棘手,要找到稳定增加或减少的结果,您可能需要使用 MySQL(尚不)支持的 MATCH_RECOGNIZE 子句。通过这种方式,您可以定义一个模式,其中每个数量都小于前一个值。此外,您可能可以使用递归 cte 来执行此操作,但这超出了我的能力范围。

这是我想出的,但需要注意的是它只比较第一个和最后一个值:

WITH
    tbl (customer, purchasedate, quantity) AS (
SELECT * FROM VALUES 
    ('Bob',         '9/1/2021',        10),
    ('Bob',         '9/10/2021',       6),
    ('Bob',         '9/18/2021',       5),
    ('Bob',         '9/19/2021',       8),
    ('Mary',        '9/1/2021',        10),
    ('Mary',        '9/10/2021',       6),
    ('Mary',        '9/18/2021',       5),
    ('Mary',        '9/19/2021',       3),
    ('Frank',       '9/1/2021',        5),
    ('Lucus',       '9/1/2021',        5),
    ('Lucus',       '9/10/2021',       6),
    ('Lucus',       '9/18/2021',       10)
)

SELECT
    DISTINCT customer
FROM
    tbl
QUALIFY
      FIRST_VALUE(quantity) OVER (partition BY customer ORDER BY purchasedate)
    > LAST_VALUE(quantity)  OVER (PARTITION BY customer ORDER BY purchasedate)

这给出了:

CUSTOMER
Bob
Mary

或者,要严格减少已知最大值,您可以将它们全部链接在一起,这会变得非常丑陋:

WITH
    tbl (customer, purchasedate, quantity) AS (
SELECT * FROM VALUES 
    ('Bob',         '9/1/2021',        10),
    ('Bob',         '9/10/2021',       6),
    ('Bob',         '9/18/2021',       5),
    ('Bob',         '9/19/2021',       8),
    ('Mary',        '9/1/2021',        10),
    ('Mary',        '9/10/2021',       6),
    ('Mary',        '9/18/2021',       5),
    ('Mary',        '9/19/2021',       3),
    ('Frank',       '9/1/2021',        5),
    ('Lucus',       '9/1/2021',        5),
    ('Lucus',       '9/10/2021',       6),
    ('Lucus',       '9/18/2021',       10)
)

SELECT
    DISTINCT customer
FROM
    tbl
    qualify 
        (NTH_VALUE(quantity, 1) OVER (partition BY customer ORDER BY purchasedate) >= NTH_VALUE(quantity, 2) OVER (partition BY customer ORDER BY purchasedate))
        and ((NTH_VALUE(quantity, 2) OVER (partition BY customer ORDER BY purchasedate) >= NTH_VALUE(quantity, 3) OVER (partition BY customer ORDER BY purchasedate)) or (NTH_VALUE(quantity, 3) OVER (partition BY customer ORDER BY purchasedate) is null))
        and ((NTH_VALUE(quantity,3) OVER (partition BY customer ORDER BY purchasedate) >= NTH_VALUE(quantity, 4) OVER (partition BY customer ORDER BY purchasedate)) or (NTH_VALUE(quantity, 4) OVER (partition BY customer ORDER BY purchasedate) is null))

这给出了:

CUSTOMER
Mary

虽然数量未知,但我认为match_recognize 将是最好的解决方案(或者您可以添加一些递归或自定义函数)。

【讨论】:

  • MySQL 不知道QUALIFY。 MySQL 5.6.41 不知道窗口函数。
  • @Akina 哦,我明白了,感谢您指出这一点,我没有意识到他使用的是较旧的 mysql。
【解决方案2】:
SELECT Customer
FROM ( SELECT CASE WHEN Customer = @customer AND Quantity > @quantity
                   THEN 1
                   ELSE 0 
                   END AS increase_detected,
              @customer := Customer Customer,
              PurchaseDate,
              @quantity := Quantity Quantity
       FROM test
       CROSS JOIN ( SELECT @customer := NULL, @quantity := NULL ) init_variables
       ORDER BY Customer, PurchaseDate
     ) subquery
GROUP BY Customer
HAVING NOT SUM(increase_detected);

https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=68b75b0df7fe4b383896e78db0caa569

【讨论】:

    猜你喜欢
    • 2014-07-30
    • 1970-01-01
    • 2020-11-12
    • 2021-11-25
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    相关资源
    最近更新 更多