同一个表上的多个查询

时间:2015-03-25 12:01:01

标签: php mysql

这是根据post post params动态生成的大查询的一部分......

有一个表user_params

id |  user_id | param_id | param_value 
--------------------------------------
1  | 5        |  2       | audi
--------------------------------------
2  | 5        |  3       | a4
--------------------------------------
3  | 5        |  4       | silver
--------------------------------------
4  | 7        |  2       | audi
--------------------------------------
5  | 7        |  3       | q3
--------------------------------------
6  | 8        |  2       | ford
--------------------------------------
7  | 8        |  3       | fiesta
--------------------------------------

我想提取所有' user_id'其中' param_id' = 1,' param_value' =' audi' ,' param_id' = 3,' param_value' =' a4'

因此,在这种情况下,我的结果应包含id行1,2,4,5,7。

考虑到这个表有超过50K的条目,最好的方法是什么?

它是InnoDB表。

+++现在我看到有一个带有这些表的多选字段的html表单。 "给我所有驾驶奥迪(a4或q3)或VW(帕萨特)的用户(user_id)是银色的#34;。

我正在测试您撰写的解决方案。

6 个答案:

答案 0 :(得分:2)

您必须在同一个表上执行多个连接。

一种方法就是这样

SELECT
    t1.user_id
FROM
    thetable AS t1,
    thetable AS t2,
    thetable AS t3
WHERE
    t1.user_id = t2.user_id AND t2.user_id=t3.user_id AND
    t1.param_id = 1 AND t1.param_value = 'audi' AND
    t2.param_id = 3 AND t2.param_value = 'a4' AND
    t3.param_id = 4 AND t3.param_value = 'silver'

这相当于使用JOIN语句,但它只是提供了这个想法。

当然,查询必须根据您要检查的参数数量进行扩展或缩小(在示例中为3)。

如果所有字段都被编入索引,则查询应该在50K记录上运行得非常快。

答案 1 :(得分:1)

如果您想加快速度,可以将索引添加到受影响的列。但实际上没有DBM应该有50k数据集的问题。它没那么多。

答案 2 :(得分:1)

好的,我实际上已经开始根据您在此处发布的示例数据创建了一个测试表,这里是创建语句:

CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `param_id` int(11) DEFAULT NULL,
  `param_value` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

接下来,我在这里用数据

填充它
INSERT INTO `test`
(
  `user_id`,
  `param_id`,
  `param_value`
)
VALUES
(5,2, 'audi'),
(5,3, 'a4'),
(5,4, 'silver'),
(7,2, 'audi'),
(7,3, 'q3'),
(8,2, 'ford'),
(8,3, 'fiesta');

然后,以下是我尝试的各种查询:

/** using OR + DISTINCT **/
SELECT DISTINCT user_id
FROM test
WHERE (param_id = 1 AND param_value = 'audi')
   OR (param_id = 3 AND param_value = 'a4')
   OR (param_id = 4 AND param_value = 'silver')

/** using OR + GROUP BY **/
SELECT user_id
FROM test
WHERE (param_id = 1 AND param_value = 'audi')
   OR (param_id = 3 AND param_value = 'a4')
   OR (param_id = 4 AND param_value = 'silver')
GROUP BY user_id


/** Using tripple join **/
SELECT
    t1.user_id
FROM
    test AS t1,
    test AS t2,
    test AS t3
WHERE
    t1.user_id = t2.user_id AND t2.user_id=t3.user_id AND
    t1.param_id = 2 AND t1.param_value = 'audi' AND
    t2.param_id = 3 AND t2.param_value = 'a4' AND
    t3.param_id = 4 AND t3.param_value = 'silver'

/** JOIN with ON clause instead of WHERE **/
SELECT
    t1.user_id
FROM
test AS t1
JOIN
test AS t2
    ON t1.user_id = t2.user_id
JOIN
test AS t3
    ON t3.user_id = t1.user_id
WHERE
    t1.param_id = 2 AND t1.param_value = 'audi' AND
    t2.param_id = 3 AND t2.param_value = 'a4' AND
    t3.param_id = 4 AND t3.param_value = 'silver'

所有这些查询都会产生相同的结果。但是,获得结果的方式确实非常不同,显示在EXPLAIN EXTENDED输出中,您现在可以通过运行所有这些查询轻松查看,并预先EXPLAIN EXTENDED,因为我&# 39;我只是懒得在ATM上粘贴所有输出

您应该看到的是JOIN个查询都显示为连接类型ALL,这意味着整个表格被扫描(3次),rows计数反映出,每个JOIN影响所有7行(总共21行) 相比之下,JOIN - 更少的查询,只需要扫描7行,我认为在这种情况下,加入可能不是答案。

答案 3 :(得分:0)

嗯,术语'param_id' = 1 AND 'param_value' = 'audi' AND 'param_id' = 3 AND 'param_value' = 'a4'总是错误的,所以我假设你想要使用(param_id = 1 AND param_value = 'audi') OR (param_id = 3 AND 'param_value' = 'a4')

在这种情况下,查询可能类似于:select distinct user_id where (param_id = 1 AND param_value = 'audi') OR (param_id = 3 AND 'param_value' = 'a4')

答案 4 :(得分:0)

如果您每次都使用AND进行尝试,则无法获得任何值。它的作用是尝试获得一个param_id为1的user_id,其值为audi,param_id为3,param_value为a4。你需要尝试使用OR,我不会看到任何param_id为1,所以要确保一个存在。如果我正确理解你的问题,你需要做一些像

这样的事情
SELECT user_id FROM tablename WHERE 'param_id' = 1 AND 'param_value' = 'audi' OR 'param_id' = 3 AND 'param_value' = 'a4'

答案 5 :(得分:0)

请在下面查询条件中的条件

where param_id in (1,3) && param_value in ('audi','a4')