我有一个包含多个连接的复杂查询,它在我的应用程序中运行多次。我想通过将此查询分解为函数内的较小部分来将此查询编写为函数。作为一个新手,我对SQL Server的了解有限。
以下是查询:
SELECT
ts.lable as label,
ts.percentage as rate
FROM
TaxSet ts
JOIN
UserInfo u ON u.userID = ?
AND u.countryID = ts.countryId
AND (ts.stateId IS NULL OR ts.stateId = 0 OR LEN(ts.stateId) < 1)
JOIN
Users us ON u.userID = us.id
JOIN
Users p ON us.parentID = p.id
AND ts.ispID = p.id
JOIN
ProductType pt ON ts.productTypeID = pt.id
WHERE
startDate <= getutcdate()
AND getutcdate() <= endDate
AND pt.identifier = ?
AND ts.id NOT IN (SELECT eu.ispTaxSettingId
FROM ExemptUsers eu
WHERE eu.ExemptUserId = ?)
现在,如何通过将此查询分解为较小的查询来编写函数。
提前致谢。
答案 0 :(得分:1)
请问您为什么要将其拆分为函数?我重新格式化了您的代码,并暂时将其放入存储过程中。我的想法是你要传递一个Identifier和UserID,它们是你查询的参数。
我修改了查询并删除了Not In语句。这已被u.id = eu.ExemptUserID上的LEFT JOIN替换为ExemptUsers,然后添加到WHERE子句以确保eu.ExemptUserID为NULL。这基本上是一种更清晰的说法&#34;如果表中存在userID,则ExemptUsers不会为该用户带回结果&#34;。
此外,我已将联接移至用户p,因为我无法以任何方式查看此内容,除非您想确保用户拥有父级?
CREATE PROCEDURE wsp_StoredProcName
(@UserID int,
@Identifier int)
AS
BEGIN
SELECT
ts.lable as label,
ts.percentage as rate
FROM
TaxSet ts
INNER JOIN UserInfo u ON u.userID = ts.UserID
AND u.countryID = ts.countryId
INNER JOIN Users us on u.userID = us.id
INNER JOIN ProductType pt on ts.productTypeID = pt.id
LEFT JOIN ExemptUsers eu on u.id = eu.ExemptUserID
WHERE
(
ts.UserID = @UserID
and pt.identifier = @Identifier
and startDate <= getutcdate()
and getutcdate() <= endDate
AND eu.ExemptUserID IS NULL
and
(
ts.stateId is null or ts.stateId = 0 or len(ts.stateId) < 1
)
)
END
答案 1 :(得分:1)
毕竟你从TaxSet中选择必须满足某些条件:日期范围,状态,与特定用户及其父级的关系,与特定产品类型的关系以及特定豁免的不存在用户。因此,在整个查询过程中使用EXISTS和NOT EXISTS,以便向读者和dbms显示您想要实现的内容。查询越简单,优化器就越容易处理它。
select
ts.lable as label,
ts.percentage as rate
from taxset ts
where getutcdate() between ts.startdate and ts.enddate
and (stateid is null or stateid between 0 and 9)
and exists
(
select *
from users u
join userinfo ui on ui.userid = u.id
where u.id = ?
and ui.countryid = ts.countryid
and u.parentid = ts.ispid
)
and exists
(
select *
from producttype pt
where pt.identifier = ?
and pt.id = ts.producttypeid
)
and not exists
(
select *
from exemptusers eu
where eu.exemptuserid = ?
and eu.isptaxsettingid = ts.id
);
正如其他人所提到的:当将查询拆分成较小的部分并分别执行时,它通常变慢而不是更快。这是因为dbms在内部以最有效的方式完成了这一操作。当然,有时dbms的优化器无法找到一个好的执行计划。您可能希望查看执行计划并检查是否认为该计划是合适的。