Postgresql for循环进行abc分析

时间:2019-02-28 13:06:53

标签: sql postgresql loops

我正在尝试进行ABC分析。我应该将所售商品归类。因此,我要尝试实现的SQL就是这个。该查询开始运行,但是即使我让它运行数小时,也不会得到任何结果,并且不会完成。当我尝试相同的查询但没有循环时-只需一组,一切都很好。有人可以帮助我弄清楚循环的问题是什么。谢谢:)

DO $$
DECLARE v integer;
BEGIN

FOR v in select id_group from ft_sales
LOOP

WITH ProductSales AS
(
    -- Get the total for each Product Model
    SELECT 
       id_group,
        id_article,
        SUM(qty) Sales
    FROM ft_sales
    WHERE id_date>2190  
GROUP BY
    id_group,
    id_article

)
-- Calculate culmulative total and categorise it based on the percentage.
-- Product Model that have high sales amount and make up the first 70% 
-- will be classified as A, the next 20% is B and the rest is C.
-- Product Models in A generate more revenue.
INSERT INTO classification ( id_group,id_article, sales, cum_sales, total, cum_perc, class )
SELECT ps.id_group,
    ps.id_article, 
    ps.Sales,
    SUM(ps.Sales) OVER (ORDER BY ps.Sales DESC) AS CumulativeSales,
    SUM(ps.Sales) OVER () AS TotalSales,
    SUM(ps.Sales) OVER (ORDER BY ps.Sales DESC) / SUM(ps.Sales) OVER () AS CumulativePercentage,
    CASE
        WHEN SUM(ps.Sales) OVER (ORDER BY ps.Sales DESC) / SUM(ps.Sales) OVER () <= 0.7 
            THEN 'A'
        WHEN SUM(ps.Sales) OVER (ORDER BY ps.Sales DESC) / SUM(ps.Sales) OVER () <= 0.9 
            THEN 'B'
        ELSE 'C'
    END AS Class
FROM    ProductSales ps
GROUP BY ps.id_group,
    ps.id_article,
    ps.Sales;
END LOOP;
    END $$; 

1 个答案:

答案 0 :(得分:0)

这可能对您有用。 免责声明:未经测试。目标是仅一次选择您需要的信息,然后循环进行插入。

DO
$$
DECLARE
    rec record;
BEGIN
    FOR rec IN
        SELECT  ps.id_group
                , ps.id_article
                , ps.Sales
                , SUM(ps.sales) OVER (ORDER BY ps.sales DESC) AS cumulative_sales
                , SUM(ps.sales) OVER () AS total_sales
                , SUM(ps.sales) OVER (ORDER BY ps.Sales DESC) / SUM(ps.Sales) OVER() AS cum_perc
                , CASE
                     WHEN SUM(ps.sales) OVER (ORDER BY ps.sales DESC) / SUM(ps.sales) OVER() <= 0.7 
                         THEN 'A'
                     WHEN SUM(ps.sales) OVER (ORDER BY ps.sales DESC) / SUM(ps.sales) OVER() <= 0.9 
                         THEN 'B'
                     ELSE 'C'
                  END AS class
        FROM
        (
            SELECT  id_group
                   , id_article
                   , SUM(qty) AS sales
            FROM ft_sales
            WHERE id_date > 2190
            GROUP BY id_group, id_article
        ) ps
    LOOP
        INSERT INTO classification ( id_group,id_article, sales, cum_sales, total, cum_perc, class )
        VALUES (rec.id_group, rec.id_article, rec.sales, rec.cumulative_sales, rec.total_sales, rec.cum_perc, rec.class)
    END LOOP;
END;
$$