MySQL查询-复杂搜索条件

标签 mysql optimization

我有一个表“位置”,其结构为:

id  | property_id | location_type
1   | 1           | 1
2   | 1           | 2
3   | 2           | 1
4   | 3           | 2
5   | 4           | 1
6   | 4           | 2

我有另一个表“便利设施”,其结构为:

id  | property_id | amenity_type
1   | 1           | 1
2   | 1           | 3
3   | 2           | 2
4   | 3           | 4
5   | 4           | 1
6   | 4           | 3

我有另一个表“属性”,其结构为:

id  | property_id | property_type
1   | 1           | 2
2   | 1           | 3
3   | 2           | 2
4   | 3           | 4
5   | 4           | 2
6   | 4           | 3

id - 是相应表的主键。 property_id 是我的数据库的属性 ID(外键)。 location_type 是海滩(值 - 1)、山(值 - 2)。

amenity_type 是汽车(值 - 1)、自行车(值 - 2)、足球(值 - 3)。

property_type 是别墅(值 - 2)、别墅(值 - 3)

您能否帮助我获取 SQL 查询来选择具有 location_type = 1 AND location_type = 2 AND amenity_type = 1 AND property_type = 3 AND property_type = 1 的 property_id,即特性有海滩、山脉、汽车、别墅和房屋.

这只是我的属性搜索应用程序中的过滤器示例。对此可以有n种组合。请分享一个通用逻辑,该逻辑将连接所有这些表并进行优化以搜索大约一百万条记录。

我还需要计算所有条件。请分享同样的查询。

[编辑计数]:

假设我得到的 (property_id with location_type = 1 AND location_type = 2 AND amenity_type = 1 AND property_type = 3 AND property_type = 1) 的计数为 1500。我需要获取具有相同条件和其他 property_type、location_type 的计数,设施类型。

例如:

1) (property_id with location_type = 1 AND location_type = 2 AND amenity_type = 1 AND property_type = 3 AND property_type = 1) AND location_type = 3 的计数

2) (property_id with location_type = 1 AND location_type = 2 AND amenity_type = 1 AND property_type = 3 AND property_type = 1) AND location_type = 4 的计数

3) (property_id with location_type = 1 AND location_type = 2 AND amenity_type = 1 的计数 AND property_type = 3 AND property_type = 1) AND amenity_type = 2

4) (property_id with location_type = 1 AND location_type = 2 AND amenity_type = 1 AND property_type = 3 AND property_type = 1) AND amenity_type = 3 的计数

等等。这对我来说是一笔很大的开销。请帮忙。另外,请注意,location_types、amenity_type、property_type 是动态的,即用户可以在主表中添加更多 location_type,而我需要获取更多 location_type 的计数。

最佳答案

在像这样有多个值的情况下,多个表没有任何问题。你在这里做的事情很好。这是您需要的查询:

select distinct l1.property_id                                                       
  from location as l1, location as l2,                                      
       amentities as a,                                                     
       properties as p1, properties as p2                                   
 where l1.property_id = l2.property_id                                      
   and l1.property_id = a.property_id                                       
   and l1.property_id = p1.property_id                                      
   and l1.property_id = p2.property_id                                      
   and l1.location_type = 1                                                 
   and l2.location_type = 2                                                 
   and a.amenity_type = 1                                                   
   and p1.property_type = 3                                                 
   and p2.property_type = 1           

一旦你明白了如何写就很容易了:

  1. 为您需要的每个表/条件组合创建一个别名
  2. 确保所有属性同时处理相同的 property_id (l1.property_id = ...)
  3. 然后指定每个表/条件的条件

您也可以显式使用“join”,但我发现上面的方法更简单,并且对数据库引擎来说应该不重要。


[从 ypercube 编辑显示 JOIN 语法]:

SELECT p.id  
FROM 
    property AS p           
  JOIN
    location AS l1
        ON  l1.property_id = p.id  
        AND l1.location_type = 1 
  JOIN
    location AS l2
        ON  l2.property_id = p.id  
        AND l2.location_type = 2 
  JOIN                      
    amentities AS a1
        ON  a1.property_id = p.id
        AND a1.amenity_type = 2                 
  JOIN
    properties AS p1
        ON  p1.property_id = p.id  
        AND p1.property_type = 3 
  JOIN
    properties AS p2 
        ON  p2.property_id = p.id  
        AND p2.property_type = 1 

[来自 ac 的评论:这和初始语法应该在内部翻译成相同的查询,因此两者同样有效]


[关于性能的编辑]一般来说,为了获得良好的数据库性能,您唯一需要担心的(或者至少是迄今为止最重要的)事情是索引。您想要在每个表的 property_id 列以及您拥有的不同类型列上声明一个索引。这很关键。但是一旦你有了这个,对于只有几百万行,这应该很快 - 上面的不是一个非常复杂的查询,并且你的数据少于 1GB(考虑使用tinyint作为类型列)。别担心...别名(“as X”)根本不是问题。


[编辑计数] 对于 count of (property_id with location_type = 1 AND location_type = 2 AND amenity_type = 1 AND property_type = 3 AND property_type = 1) AND location_type = X 您想要类似以下内容:

select lx.location_id, count(l1.property_id)
  from location as l1, location as l2, location as lx
       amentities as a,
       properties as p1, properties as p2
 where l1.property_id = l2.property_id
   and l1.property_id = a.property_id
   and l1.property_id = p1.property_id
   and l1.property_id = p2.property_id
   and l1.property_id = lx.property_id
   and l1.location_type = 1
   and l2.location_type = 2
   and a.amenity_type = 1
   and p1.property_type = 3
   and p2.property_type = 1
 group by lx.location_type

但我还没有测试过它或任何东西。这应该会为您提供多行,其中包含每一行的 location_type 和计数(因此您可以在一个查询中执行上面给出的所有查询)。

关于MySQL查询-复杂搜索条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7053627/

相关文章:

Matlab lsqcurvefit() 函数的 Python 等价性

optimization - 如何在 OpenShift 3.6 中获取有关最新成功部署 pod 的信息

Mysql针对每种类型的field2查找不在同一个表中的所有项目

algorithm - CPLEX 提供具有不同目标值的不同最佳解决方案

mysql - 我想按姓氏对我的表进行分区?

c# - 无法将属性名称用作 dbset Entity Framework 的类名称

php - 计算每个用户在系统上消耗的时间的有效方法

algorithm - 与所有其他给定点的曼哈顿距离最小的所有点[优化]

php - CodeIgniter DataMapper ORM v1.8.0 - 如何从多个表中获取记录

javascript - 尝试 POST 时无法从请求正文获取对象的值 [Node.js、MySQL]