我目前正在研究一个特别复杂的用例。简化如下:)
首先,客户记录与服务集合具有多对一的关系,也就是说,单个客户可能有多个与之关联的服务。
在我的触发器中,我正在编写一个查询,该查询根据某些条件返回客户的 ID。标准如下,
- 如果至少有一项服务属于 B 类型,并且不存在 A 类型的服务,则返回 id
- 如果至少有一项服务属于 C 类型,并且不存在 B 或 A 类型的服务,则返回 id
- 如果至少有一项服务属于 D 类型,并且不存在 C 或 B 或 A 类型的服务,则返回 id
我目前的方法是形成一个类似于下面的查询
SELECT c.ClientId
FROM
Clients AS c
-- actually INNER JOIN is superfluous in this sample, but required for
-- other auxilliary criteria i have left out. illustrates relationship
-- between Clients and Services table
INNER JOIN Services AS s ON c.ClientId = s.ClientId
WHERE
-- has at least one service of type B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A'))) OR
-- has at least one service of type C, no B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A'))) OR
-- has at least one service of type D, no C, no B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'D')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A')))
where[dbo].[Get_ServicesByClientIdAndType]
是返回指定客户端 ID 和服务类型的关联服务的函数。如同
-- this query is actually significantly more complex than shown
-- below, but this illustrates use of parameters client id and
-- service type
SELECT s.ServiceType
FROM
Services AS s
WHERE
s.ClientId = @clientId AND
s.ServiceType = @serviceType
假设这是表达此用例的最佳方式,是否[dbo].[Get_ServicesByClientIdAndType]
会缓存函数子查询,或者更改服务参数是否需要每次调用都进行新的评估?[我正在调用这个东西 9 次!!!运行 SQL Server 2005]
我知道 Sql Server 2005 支持一些子查询优化,例如缓存结果,但我不确定在什么情况下或如何形成我的子查询[或函数],以便充分利用 Sql Server 的功能。
编辑:回顾了我上面的标准,并且不能放弃一种唠叨的感觉,有些事情已经过去了。我在脑海中玩弄了一些逻辑,并想出了这个[更简单的]公式
SELECT c.ClientId
FROM
Clients AS c
INNER JOIN Services AS s ON c.ClientId = s.ClientId
WHERE
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A')) AND
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) OR
EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) OR
EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'D')))
本质上,不存在涉及 B 会导致拒绝的场景,对于 C 和 D 也是如此,因此任何配置都是可以接受的。我们只关心 A 在任何选择中都不存在。精氨酸!查理·布朗!
将这两个表达式都留待审查,我仍然非常感谢有关 Sql Server 性能 wrt 用户定义函数的响应。