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 ;
我正在编写一个程序,根据过滤条件从数据库 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 ;