【问题标题】:Executing functions inside other functions在其他函数中执行函数
【发布时间】:2019-10-14 06:55:01
【问题描述】:

我需要创建一个 SINGLE 函数来查看两个不同的表(通过连接其他表创建)BRANDS_TYPES 和 PRODUCTS_LAUNCH。它们具有以下结构。

| id | brand_name   | type   |  
| 1  | porsche      | sports |  
| 1  | porsche      | suvs   |  

| id | brand_name  |  prod   | prod_date | sales  | group | prod_remain |  
|  1 | porsche     | carrera |      1991 | 500000 |     1 |           5 |  

我需要返回一个表格,其中包含 top x sales 中的 brands,用于 单个组的选择类型 。品牌自选定日期以来必须至少推出 1 次产品。返回表应汇总按品牌分组并按销售额排序的销售额以及剩余产品最少的品牌。 我不知道如何将这些不同的查询合并到一个函数中。

我已经设法将“程序”分成三个不同的部分,因为它们对于初学者(我)来说并不过分复杂。第一个函数获取所有具有特定类型的品牌。第二个查看 PRODUCTS_LAUNCH 并返回在特定日期之后至少推出 1 种产品且属于某个组的品牌。第三个函数查看 PRODUCTS_LAUNCH 并返回一个表格,其中包含剩余产品最少且销售额最多的品牌的排名顺序。

CREATE OR REPLACE FUNCTION get_type (type_choice VARCHAR)  
    RETURNS TABLE (  
    g_type_name brands_types.type%TYPE,   
    g_brand_id brands_types.brand_id%TYPE,  
    g_brand_name brands_types.brand_name%TYPE)  
AS $$  
BEGIN  
    RETURN QUERY SELECT   
        type_name,  
        brand_id,  
        brand_name  
    FROM brands_types WHERE type ILIKE type_choice;  
END; $$     

CREATE OR REPLACE FUNCTION get_group_date (cutoff_date DATE, group_choice INT)
    RETURNS TABLE ( 
    r_brand_name products_launch.brand_name%TYPE,
    r_date_l products_launch.prod_date%TYPE,
    r_sales products_launch.sales%TYPE,
    r_group products_launch.group%TYPE,
    r_remaining products_launch.prod_remain%TYPE)
AS $$
DECLARE
    i_row record;
BEGIN
    FOR i_row IN 
        (SELECT  
            brand_name,
            prod_date,
            sales,
            group,
            prod_remain
        FROM 
            products_launch
        WHERE prod_date >= cutoff_date AND group = group_choice)
    LOOP
        r_brand_name := upper(i_row.brand_name);
        r_date_l := i_row.prod_date;
        r_sales := i_row.sales;
        r_group := i_row.group;
        r_remaining := i_row.prod_remain;
        RETURN NEXT;
    END LOOP;
END;
$$

CREATE OR REPLACE FUNCTION get_topsales_prodleft (top_t1 INT)
    RETURNS TABLE (
        tp_brand_name products_launch.brand_name%TYPE,
        tp_remaining products_launch.prod_remain%TYPE,  
        tp_sales products_launch.sales%TYPE
        )
AS $$
BEGIN 
    RETURN QUERY        
        SELECT 
            brand_name,
            prod_remain,
            SUM (sales) AS total_sales
        FROM
            products_launch
        GROUP BY
            brand_name,
            prod_remain
        ORDER BY prod_remain DESC, total_sales DESC
        LIMIT top_t1;
END;
$$

每个功能都按预期工作(我认为)但是我需要一个功能。我如何在另一个内部调用并查询其返回?

【问题讨论】:

    标签: postgresql plpgsql


    【解决方案1】:

    首先我建议简化一下:

    CREATE OR REPLACE FUNCTION get_type (type_choice VARCHAR)  
        RETURNS SETOF brands_types
        LANGUAGE SQL
    AS $$
        SELECT *
        FROM brands_types
        WHERE type ILIKE type_choice;  
    $$     
    CREATE OR REPLACE FUNCTION get_group_date (cutoff_date DATE, group_choice INT)
        RETURNS SETOF products_launch
        LANGUAGE SQL
    AS $$
        SELECT
            upper(brand_name) AS brand_name,
            prod_date,
            sales,
            group,
            prod_remain
        FROM 
            products_launch
        WHERE prod_date >= cutoff_date AND group = group_choice;
    $$
    CREATE OR REPLACE FUNCTION get_topsales_prodleft (top_t1 INT)
        RETURNS SETOF products_launch
        LANGUAGE SQL
    AS $$
        SELECT 
            brand_name,
            prod_remain,
            SUM (sales) AS total_sales
        FROM
            products_launch
        GROUP BY
            brand_name,
            prod_remain
        ORDER BY prod_remain DESC, total_sales DESC
        LIMIT top_t1;
    $$
    

    现在要将它们加入到单个查询中,您需要做的就是将类型与按品牌名称发布,并以此过滤您的总和:

    SELECT *
    FROM get_topsales_prodleft($1)
    WHERE brand_name IN (SELECT brand_name
                         FROM get_type($2)
                         JOIN get_group_date($3, $4) USING (brand_name))
    

    为了使其按预期工作,我认为您 a) 需要将 LIMIT 放在外部过滤查询上,而不是在 get_topsales_prodleft 函数内,并且您需要删除 upper() 调用brand_name 中的 get_group_date,否则连接将不起作用。

    此外,我相信在单个语句中编写查询而不是使用任何函数会更简单 - 或者至少不那么冗长。它会到达

    SELECT *
        brand_name,
        prod_remain,
        SUM (sales) AS total_sales
    FROM
        products_launch
    WHERE
        brand_name IN (SELECT brand_name
                       FROM brands_types
                       JOIN products_launch USING (brand_name)
                       WHERE type ILIKE :type_choice
                        AND  prod_date >= :cutoff_date AND group = :group_choice)
    GROUP BY
        brand_name,
        prod_remain
    ORDER BY prod_remain DESC, total_sales DESC
    LIMIT :top_t1;
    

    【讨论】:

    • 感谢您的回复。不得不适应 PLPGSQL 但工作正常。是的,我最终对整个事情做了一个查询。
    猜你喜欢
    • 2019-03-01
    • 1970-01-01
    • 2019-03-17
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 2021-01-07
    • 2018-06-09
    相关资源
    最近更新 更多