SELECT基于WHERE或JOIN

时间:2017-04-03 23:57:55

标签: mysql sql join

我有下表(从我的实际代码中简化):

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

2 个答案:

答案 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