SELECT 查询以使用可选的用户提供的参数过滤记录

SELECT query to filter records using optional user-supplied parameters

我正在编写一个程序,根据过滤条件从数据库 table 中抓取记录。现在用户可以应用过滤器也可以不应用。因此,将根据该过滤条件应用。

即如果过滤器参数将包含任何值而不是仅它将应用条件。

注意:我可以通过if..else..condition来实现,然后分别执行不同的查询来得到我想要的输出.但我想问的是,有没有比 if..else..

更好的方法呢?

示例(此处i_status_id、i_category_id可能包含任何值,也可能不包含任何值)

DELIMITER $$

DROP PROCEDURE IF EXISTS `FilterRecord`$$

CREATE PROCEDURE `FilterRecord`(IN i_status_id BIGINT,IN i_category_id BIGINT)
BEGIN  
    SELECT 
            Item_backlog.backlog_id AS backlog_id,
            Item_backlog.title AS backlog_name,
            Item_backlog_Group.title AS group_Name,
            Item_backlog.description AS description,
            Item_backlog.est_start_date AS estimated_start_date,
            Item_backlog.est_end_date AS estimated_end_date,
            Item_backlog.actual_start_date AS actual_start_date,
            Item_backlog.actual_end_date AS actual_end_date,
            Item_backlog.estimated_hours AS estimated_hours,
            Item_backlog.actual_hours AS actual_hours,
            Item_backlog.status_id AS status_id,
            APV_Status.name AS status_name ,
            Item_backlog.priority_id AS priority_id,
            APV_Priority.name AS priority_name,
            Item_backlog.rank AS rank,
            Item_backlog.isActive AS isActive,
            Item_backlog.created_by_id AS created_by_id,
            Item_backlog.created_on AS created_on,
            Item_backlog.modified_by_id AS modified_by_id,
            Item_backlog.modified_on AS modified_on
        FROM 
            Item_backlog 
        INNER JOIN     
            ApplicationParamValue AS APV_Status ON (Item_backlog.status_id=APV_Status.appParamValueId)
        INNER JOIN    
            ApplicationParamValue AS APV_Priority ON (Item_backlog.Priority_Id=APV_Priority.appParamValueId)
        INNER JOIN 
            Item_backlog_group AS Item_backlog_Group ON (Item_backlog.backlog_group_id=Item_backlog_Group.backlog_group_id)
        WHERE 
            Item_backlog.status_id=i_status_id
        AND
            Item_backlog.category_id=i_category_id

END$$

DELIMITER ;

假设您有一个定义的值来指示何时未指定参数(例如,我在下面使用 NULL 来指示未提供参数),您可以执行以下操作有条件地应用参数。

CREATE PROCEDURE `FilterRecord`(IN i_status_id BIGINT,IN i_category_id BIGINT)
BEGIN  
    SELECT 
            Item_backlog.backlog_id AS backlog_id,
            -- ...
        FROM 
            Item_backlog 
        INNER JOIN     
           -- ..
        WHERE 
            (Item_backlog.status_id=i_status_id OR i_status_id IS NULL)
        AND
            (Item_backlog.category_id=i_category_id OR i_category_id IS NULL);
END

但是请注意,这样做的性能可能会降低。

SqlFiddle example here - 我假设 MySql,顺便说一句,根据您的主要标签和反引号。

在下面尝试,它将根据传递的参数应用过滤条件:

DELIMITER $$

DROP PROCEDURE IF EXISTS `FilterRecord`$$

CREATE PROCEDURE `FilterRecord`(IN i_status_id BIGINT,IN i_category_id BIGINT)
BEGIN  

    DECLARE Var_status_id VARCHAR(200);
    DECLARE Var_category_id VARCHAR(200);
DECLARE andCondition VARCHAR(200);


    IF i_status_id<>0 THEN 
        SET Var_status_id=CONCAT(' (Item_backlog.status_id = ', i_status_id,')');
        SET andCondition ='AND';
    ELSE 
        SET Var_status_id="";
        SET andCondition ='';
    END IF;


    IF i_category_id<>0 THEN 
        SET Var_category_id=CONCAT(andCondition,' (Item_artifact_category_mapping.category_id = ', i_category_id,')');
    ELSE 
        SET Var_category_id="";
    END IF;


    SET @SQL := CONCAT('SELECT 
            Item_backlog.backlog_id AS backlog_id,
            Item_backlog.title AS backlog_name,
            Item_backlog_Group.title AS group_Name,
            Item_backlog.description AS description,
            Item_backlog.est_start_date AS estimated_start_date,
            Item_backlog.est_end_date AS estimated_end_date,
            Item_backlog.actual_start_date AS actual_start_date,
            Item_backlog.actual_end_date AS actual_end_date,
            Item_backlog.estimated_hours AS estimated_hours,
            Item_backlog.actual_hours AS actual_hours,
            Item_backlog.status_id AS status_id,
            APV_Status.name AS status_name ,
            Item_backlog.priority_id AS priority_id,
            APV_Priority.name AS priority_name,
            Item_backlog.rank AS rank,
            Item_backlog.isActive AS isActive,
            Item_backlog.created_by_id AS created_by_id,
            Item_backlog.created_on AS created_on,
            Item_backlog.modified_by_id AS modified_by_id,
            Item_backlog.modified_on AS modified_on
        FROM 
            Item_backlog 
        INNER JOIN     
            ApplicationParamValue AS APV_Status ON (Item_backlog.status_id=APV_Status.appParamValueId)
        INNER JOIN    
            ApplicationParamValue AS APV_Priority ON (Item_backlog.Priority_Id=APV_Priority.appParamValueId)
        INNER JOIN 
            Item_backlog_group AS Item_backlog_Group ON (Item_backlog.backlog_group_id=Item_backlog_Group.backlog_group_id)
        WHERE', Var_status_id, Var_category_id);

        PREPARE stmt FROM @SQL; 
        EXECUTE stmt;

END$$

DELIMITER ;