MYSQL LEFT JOIN 返回重复表的结果
Posted
技术标签:
【中文标题】MYSQL LEFT JOIN 返回重复表的结果【英文标题】:MYSQL LEFT JOIN returning duplicate table a results 【发布时间】:2012-03-27 06:58:13 【问题描述】:更新滚动到bottem for sql代码和输出 我最近开始研究公寓数据库。该数据库包含 2 个表
表“属性”存储有关公寓大楼的基本信息(联系信息和照片)。它被propid
列引用
表 b“平面图”存储有关出租的各个单元的信息。价格信息、面积和公寓类型。 floorplan
表也被 propid
列引用,以允许我们将 2 个表链接在一起。它也有自己的唯一标识符,但未被使用。
每个综合体通常有 5-10 个平面图。
我正在我们的网站上为我们的客户创建一个前端搜索界面。我需要能够搜索具有满足搜索条件的平面图的属性。但是在执行 join 语句时,我注意到每次发现其中一个平面图与搜索条件匹配时,它都会给我一个包含相同属性的列表。
我对这个主题做了一些研究。最常见的答案使用 SELECT DISTINCT。
问题是我需要的不仅仅是作为结果返回的 propid。
我试着做这样的事情:
SELECT DISTINCT (p.propid), p.*, f.* FROM property AS p
LEFT JOIN floorplans AS f ON p.propid = f.propid
WHERE f.pricespecial BETWEEN [min_price] AND [max_price];
[min_price]
和[max_price]
由用户提供。
预期结果将是具有满足所有用户搜索条件的平面图的所有属性的列表。但我不希望为每个匹配单元返回相同的属性。
当我运行这个查询时,我仍然得到重复的属性
过去我只是简单地在包含数据的 xml 提要上运行一个过滤器脚本。该脚本将确定 givin 属性中的最高和最低价格单位,并将这些值添加到属性表 price_min
和 price_max
上的两个新创建的列中。到目前为止,这已经足够好了,但该公司一直在推动更准确的搜索结果。
我看到的唯一其他选择是只运行查询,只返回 DISTINCT propid。然后运行第二个查询以检索实际数据。
I.E.
$sql = "SELECT DISTINCT p.propid FROM property as f" .
"LEFT JOIN floorplans AS f" .
"WHERE f.price BETWEEN " . $_REQUEST['price_min'] . " AND " . $_REQUEST['price_max'] . "
编辑**
使用新修订的 sql 语句的一些示例输出。
propid name pricespecial
4230A 2222 Smith Street $1225-1450
4230A 2222 Smith Street $1895-2045
4230A 2222 Smith Street $2220
4679A City Place Midtown $1230-1599
4679A City Place Midtown $1595-1650
4679A City Place Midtown $1699-2195
4572A Gables Memorial Hills $1308-2159
4572A Gables Memorial Hills $2050-2693
4606A Venue Museum District $1535-1930
4606A Venue Museum District $1980-2550
我无法将此作为评论发布,所以我只是编辑了我的问题。
【问题讨论】:
您已将f.*
包含在您的SELECT
中,但我不清楚您是否希望返回这些值。你呢?
是的,我想要两个表中的所有值,但我只想要不同的 propid 列。输出是包含平面图详细信息的属性列表,因此最终我将从平面图表中过滤掉我不需要的字段,但为了简单起见,假设我想要两个表中的所有数据,但只有一个来自每个属性条目。
我不认为我跟随。如果 floorplans 有 5 个给定属性的记录,您说您想查看 5 个平面图但只有 1 个属性?也许尝试添加一个包含您希望看到的示例结果的表格。
因此,如果单个属性存在两个平面图,您需要平面图中的数据,但不重复属性信息?那么您的代码是否知道第二行数据中的平面图与前一条记录的属性相匹配?
旁注,只需等待有人更改请求并将price_max
设置为1; DROP DATABASE; --
。
【参考方案1】:
你得到这些骗子是因为你要求他们。
你想要
SELECT DISTINCT p.propid, p.*
FROM property AS p
LEFT JOIN floorplans AS f ON p.propid = f.propid
WHERE f.price BETWEEN [min_price] AND [max_price]
当您说SELECT ..., f.*
时,请给我回复property
和floorplan
的每个不同组合。但您只需要不同的 property
项目。
一般来说,拼出您想要的特定列是个好主意。避免p.*
检索所有列。当您使用SELECT DISTINCT
时尤其如此。
【讨论】:
我确定他想要一个 INNER JOIN,因为条件基于平面图表中的信息。 在尝试发布一些代码时遇到评论问题 这一定是我用过的最糟糕的评论系统【参考方案2】:我更喜欢没有区别的:
SELECT p.*
FROM property AS p
WHERE EXISTS (SELECT NULL FROM floorplans AS f WHERE f.propid = p.propid AND f.price BETWEEN [min_price] AND [max_price])
【讨论】:
天哪,你的天才尼古拉工作得很好。也许你会愿意解释它背后的逻辑,我不太明白。但它确实有效。 当然。子查询(在括号中选择)以通常的方式选择行,但有一个例外:它通过 f.propid = p.propid 连接到主查询。 Exists 检查是否返回一行,如果返回则为真。如果您不需要来自相关行的任何数据但只需要检查其中一个是否满足某些条件,请使用它,因为它通常比连接更快 - 它只需要建立匹配而不返回任何数据,因此在 select 中为 null列表(不是必需的,但我喜欢这样)。 说我想包含平面图表中的数据。我是否也可以使用此语句,只需将 null 替换为必填字段? @Dean 不,你不会,这就是为什么我在评论中提前询问你是否需要平面图表中的任何数据。 拥有平面图数据并不是绝对必要的。但是属性表不包含定价信息,因此在尝试显示列表时,我想我可以根据需要使用第二条语句提取平面图,一旦我从您之前的答案中检索到属性列表。但是,如果您知道我如何在单个 select 语句中做到这一点,那就太棒了。但是我确实知道一些变得过于复杂的连接查询需要更长的时间才能检索,因此第二个查询可能是更好的选择。以上是关于MYSQL LEFT JOIN 返回重复表的结果的主要内容,如果未能解决你的问题,请参考以下文章
MySQL # left join 语句,对右表的限制条件使用注意问题