仅返回具有连续升序或降序值的条目

时间:2014-07-22 15:13:08

标签: sql postgresql

我有一个包含以下值的表:

客户|周末| trailing_avg

客户定义客户输入,周末是每周值,尾随平均值是利用率指标。

我想过滤结果,只显示最近(即最高周末)trailing_avg值连续升序或降序的客户。

因此,如果客户A的最新尾随平均值为7,6,5,则会显示,但如果客户B的平均值为7,8,6,则他们不会。

2 个答案:

答案 0 :(得分:0)

你可以创建一个函数,只是为了评估trailing_avg中的趋势,然后让那个构建然后简单的查询来带你去。

看看下面的代码。 这是我的快乐即兴,但希望能帮到你。

DELIMITER //

DROP FUNCTION IF EXISTS f_trend//
CREATE FUNCTION f_trend (trend VARCHAR(100))

    RETURNS TEXT 

    BEGIN

    DECLARE cnt TEXT;

    SET @p = trend;
    SET @p_1n = 0;
    SET @p_2n = 0;
    SET @c = 0;
    SET @diff = 0;
    SET @d = 0;

    label1: LOOP

    SET @c = @c + 1;

    SET @p_1n = SUBSTRING_INDEX(@p,',',1);

    SET @p_2n = SUBSTRING_INDEX(
    REPLACE(@p,CONCAT(@p_1n,','),''),',',1);

    SET @p = REPLACE(@p,CONCAT(SUBSTRING_INDEX(@p,',',1),','),'');

    SET @diff = @p_2n - @p_1n;

    IF @diff > 0 AND ABS(@d) = (@c-1) THEN SET @d = @d + 1;
    ELSEIF @diff < 0 AND ABS(@d) = (@c-1) THEN  SET @d = @d - 1;
    ELSE SET @d = @d;
    END IF;

    IF @c >= LENGTH(trend) - LENGTH(REPLACE(trend, ',', '')) THEN
        LEAVE label1;
    END IF;

    ITERATE label1;

    END LOOP label1;

    IF abs(@d) = @c AND @d > 0 THEN 
        SET cnt=(SELECT 'ASC');
    ELSEIF abs(@d) = @c AND @d < 0 THEN
        SET cnt=(SELECT 'DESC');
    ELSE SET cnt=(SELECT 'N/A');
    END IF;

    RETURN cnt;

    END //

DELIMITER ;

用于检索所需内容的查询:

SELECT customer 
FROM info
WHERE weekending = (SELECT MAX(weekending) FROM info) 
AND f_trend(trainling_avg) IN ('ASC','DESC');

这不是最佳选择,但一切都取决于您的需求和规模。

答案 1 :(得分:0)

没有日期范围的查询。

WITH tmpt AS (
   select Customer, 
          weekending, 
          trailing_avg, 
          CASE WHEN trailing_avg + 1 = LEAD(trailing_avg, 1) OVER(ORDER BY Customer, weekending,trailing_avg) THEN 1 ELSE 0 END AS flg,
          CASE WHEN trailing_avg + 1 = LAG(trailing_avg, 1) OVER(ORDER BY customer,weekending,trailing_avg) THEN 1 ELSE 0 END AS flg1
   FROM test
), Customer AS (
   SELECT Customer, count(flg) AS flg, count(flg1) AS flg1 
   FROM tmpt 
   WHERE flg1 = 0 AND flg = 0 GROUP BY Customer
)
SELECT * FROM test WHERE Customer IN (SELECT Customer FROM Customer WHERE flg + flg1 = 2);

我明白出了什么问题 忘了添加PARTITION BY Customer

// trailing_avg < if step metric random or trailing_avg + 1 if step metric only +/-1
-CASE WHEN trailing_avg + 1 = LEAD(trailing_avg, 1) OVER(ORDER BY Customer, weekending,trailing_avg) THEN 1 ELSE 0 END AS flg,
-CASE WHEN trailing_avg + 1 = LAG(trailing_avg, 1) OVER(ORDER BY customer,weekending,trailing_avg) THEN 1 ELSE 0 END AS flg1
+CASE WHEN trailing_avg < LEAD(trailing_avg, 1) OVER(PARTITION BY Customer ORDER BY  weekending,trailing_avg) THEN 1 ELSE 0 END AS flg,
+CASE WHEN trailing_avg < LAG(trailing_avg, 1) OVER(PARTITION BY Customer ORDER BY weekending,trailing_avg) THEN 1 ELSE 0 END AS flg1 
改变的例子:
WITH tmpt AS (
   select Customer,
          weekending,
          trailing_avg,
          CASE WHEN trailing_avg < LEAD(trailing_avg, 1) OVER(PARTITION BY Customer ORDER BY  weekending,trailing_avg) THEN 1 ELSE 0 END AS flg,
          CASE WHEN trailing_avg < LAG(trailing_avg, 1) OVER(PARTITION BY Customer ORDER BY weekending,trailing_avg) THEN 1 ELSE 0 END AS flg1 
          FROM test
), Customer AS (
   SELECT Customer, count(flg) AS flg, count(flg1) AS flg1
   FROM tmpt
   WHERE flg1 = 0 AND flg = 0 GROUP BY Customer
)
SELECT * FROM test WHERE Customer IN (SELECT Customer FROM Customer WHERE flg + flg1 = 2);