我有可选的参数化存储过程,但查询工作正常并且在表上有适当的索引。但是当最后一个参数传递时i:e部门代码和其他参数可以为NULL。查询需要很长时间而不会产生结果。时间不断增加但结果永远不会被检索。
有关如何跳过未使用的联接的任何建议,这与此方案中无关。
在这种情况下,我可以跳过下面的加入。
LEFT JOIN EMPLOYEEADDRESS EA ON EA.EmployeeDetailsFK = ED.Id
任何建议如何避免此连接以使查询执行更快。
请在下面找到完整的查询
CREATE PROCEDURE prGetStudentData
(
@FirstName VARCHAR(50) = NULL,
@EmployeeCode VARCHAR(50) = NULL,
@Address VARCHAR(50) = NULL,
@DepartmentCode VARCHAR(50) = NULL
)
AS
BEGIN
SELECT E.* FROM EMPLOYEE E
INNER JOIN EMPLOYEEDETAILS ED ON ED.EmployeeFK = E.Id
LEFT JOIN EMPLOYEEADDRESS EA ON EA.EmployeeDetailsFK = ED.Id
LEFT JOIN DEPARTMENT D ON D.Id = ED.DepartmentFK
WHERE (@FirstName IS NULL OR (E.FirstName = @FirstName) AND
(@EmployeeCode IS NULL OR (ED.EmployeeCode = @EmployeeCode) AND
(@Address IS NULL OR (EA.Address = @Address) AND
(@DepartmentCode IS NULL OR (D.DepartmentCode = @DepartmentCode)
END
答案 0 :(得分:1)
一个简单的答案是有条件地选择一个选择。
CREATE PROCEDURE prGetStudentData (
@FirstName VARCHAR(50) = NULL,
@EmployeeCode VARCHAR(50) = NULL,
@Address VARCHAR(50) = NULL,
@DepartmentCode VARCHAR(50) = NULL
) AS BEGIN
IF @DepartmentCode IS NULL
SELECT E.*
FROM EMPLOYEE E
INNER JOIN EMPLOYEEDETAILS ED ON ED.EmployeeFK = E.Id
LEFT JOIN EMPLOYEEADDRESS EA ON EA.EmployeeDetailsFK = ED.Id
LEFT JOIN DEPARTMENT D ON D.Id = ED.DepartmentFK
WHERE (@FirstName IS NULL OR (E.FirstName = @FirstName)
AND (@EmployeeCode IS NULL OR (ED.EmployeeCode = @EmployeeCode)
AND (@Address IS NULL OR (EA.Address = @Address)
AND (@DepartmentCode IS NULL OR (D.DepartmentCode = @DepartmentCode)
ELSE
SELECT E.*
FROM EMPLOYEE E
INNER JOIN EMPLOYEEDETAILS ED ON ED.EmployeeFK = E.Id
LEFT JOIN EMPLOYEEADDRESS EA ON EA.EmployeeDetailsFK = ED.Id
WHERE (@FirstName IS NULL OR (E.FirstName = @FirstName)
AND (@EmployeeCode IS NULL OR (ED.EmployeeCode = @EmployeeCode)
AND (@Address IS NULL OR (EA.Address = @Address)
END
答案 1 :(得分:1)
试试这个:
SELECT E.* FROM EMPLOYEE E
INNER JOIN EMPLOYEEDETAILS ED ON ED.EmployeeFK = E.Id
LEFT JOIN EMPLOYEEADDRESS EA ON EA.EmployeeDetailsFK = ED.Id
LEFT JOIN DEPARTMENT D ON @DepartmentCode IS NOT NULL AND D.Id = ED.DepartmentFK
WHERE (@FirstName IS NULL OR (E.FirstName = @FirstName)) AND
(@EmployeeCode IS NULL OR (ED.EmployeeCode = @EmployeeCode)) AND
(@Address IS NULL OR (EA.Address = @Address)) AND
(@DepartmentCode IS NULL OR (D.DepartmentCode = @DepartmentCode))
或
SELECT E.* FROM EMPLOYEE E
INNER JOIN EMPLOYEEDETAILS ED ON ED.EmployeeFK = E.Id
LEFT JOIN EMPLOYEEADDRESS EA ON EA.EmployeeDetailsFK = ED.Id
WHERE (@FirstName IS NULL OR (E.FirstName = @FirstName) AND
(@EmployeeCode IS NULL OR (ED.EmployeeCode = @EmployeeCode) AND
(@Address IS NULL OR (EA.Address = @Address) AND
(@DepartmentCode IS NULL OR
EXISTS(SELECT *
FROM DEPARTMENT D
WHERE D.Id = ED.DepartmentFK
AND D.DepartmentCode = @DepartmentCode)
)
答案 2 :(得分:1)
具有多个可选输入参数的存储过程可能会有问题。执行搜索功能的存储过程就是很好的例子。
在SQL中编写此类查询的一种常见方法是在(WHERE SomeColumn = @SomeVariable OR @SomeVariable IS NULL)
形式的where子句中使用多个谓词。虽然这有效,但问题在于它的工作效率相当低。在大型表上,它可能导致查询性能非常差。
通常,更好的选择是通过sp_executesql
使用参数化动态sql。查看Gail Shaw's Catch-All Queries博文。