我有下表(从我的实际代码中简化):
CREATE TABLE `policy` (
`policy_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`policy_number` varchar(25) DEFAULT NULL,
`effective_date` datetime NOT NULL,
PRIMARY KEY (`policy_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
我希望能够通过传递策略ID来从表中选择一行:
SELECT * FROM policy WHERE policy_id = pol_id;
或者我希望能够获取多行。我决定使用另一个表来存储行,然后在该表上连接到我的策略表。这消除了使用FIND_IN_SET的需要。
表格:
CREATE TABLE `policy_population_ids` (
`policy_population_id` int(10) unsigned NOT NULL,
`policy_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`policy_id`,`policy_population_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
查询:
SELECT * FROM policy JOIN policy_population USING (policy_id) WHERE policy_population_id = pp_id;
我目前有一个存储过程,它接受pol_id和pp_id,并根据填充的那个,执行一个查询或另一个查询。但是,这意味着我要保持两倍的代码(实际的查询加入了几个表,并且更复杂,有些工作要维护),我想将它们组合起来。
我想出的综合查询是:
SELECT
policy_id,
policy_number,
effective_date
FROM
policy AS p
LEFT JOIN
policy_population AS pp ON p.policy_id = pp.policy AND pp_id IS NOT NULL
WHERE
(pol_id IS NULL OR policy_id = pol_id) AND
(pp_id IS NULL OR policy_population_id = pp_id);
但是,使用填充表(使用pp_id)时,此查询的效率非常低,因为策略表有数百万行。有没有办法让这个更有效率?我应该回过头来使用带有if / else的两个单独的查询吗?
更新
以下是样本数据和预期结果。
政策表:
policy_id policy_number effective_date
203 ABC1 12/16/2011 18:42
204 ABC2 12/16/2011 21:16
205 ABC3 12/16/2011 23:11
207 ABC4 12/17/2011 17:06
208 ABC5 12/17/2011 17:17
policy_population_ids表:
policy_population_id policy_id
23456 203
23456 204
23456 205
23457 207
23457 208
如果我传递了一个204的pol_id,我会得到:
204 ABC2 12/16/2011 21:16
如果我通过了44456的pp_id,我会得到:
203 ABC1 12/16/2011 18:42
204 ABC2 12/16/2011 21:16
205 ABC3 12/16/2011 23:11
答案 0 :(得分:0)
你应该在policy_population.policy_id上有一个索引。这样,连接将更快地运行。
答案 1 :(得分:0)
将查询构建为字符串,并且只有在传递相关参数时才包含对policy_population表的连接。然后,执行字符串。
DECLARE @include_policy_population VARCHAR(200)
,@sql NVARCHAR(MAX)
IF (@pol_id IS NOT NULL)
SELECT @include_policy_population = 'INNER JOIN policy_population ON policy_population.policy_id = policy.policy_id'
ELSE
SELECT @include_policy_population = ''
SELECT @sql = N'SELECT *
FROM policy
' + @include_policy_population + '
INNER JOIN ....
INNER JOIN ....'
EXEC sp_executesql @sql