搜索两个查询并消除没有关系的行的最佳方法

时间:2011-09-25 11:00:58

标签: mysql coldfusion

我正在一个物业网站上工作并拥有财产和单位的记录集,单位与财产有一对多的关系。我想弄清楚的是如何最好地创建一个搜索功能,它将根据两者的标准输出结果。因此,如果我搜索位于曼彻斯特的房产和一个拥有永久业权期限的单位,我想要删除所有没有永久业权的单位的房产。

我考虑过的一个潜在的解决方案是为符合属性条件的属性创建记录集,然后为符合单位条件的单位创建单位记录集,然后最后遍历服务器端的属性记录集代码并消除与单元记录集中任何单元无关的任何属性。真的不确定这是不是最好的做事方式,所以会热衷于听到任何建议吗?

由于

编辑(添加了表结构和MySQL):

--
-- Table structure for table `property`
--

CREATE TABLE IF NOT EXISTS `property` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `street` text NOT NULL,
  `town` text NOT NULL,
  `postcode` text NOT NULL,
  `description` longtext NOT NULL,
  `team_member` varchar(255) NOT NULL DEFAULT '',
  `pdf` text NOT NULL,
  `default_image_id` int(11) DEFAULT NULL,
  `virtual_tour_link` text NOT NULL,
  `date` date NOT NULL DEFAULT '0000-00-00',
  `archive` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='' AUTO_INCREMENT=13 ;

--
-- Table structure for table `unit`
--

CREATE TABLE IF NOT EXISTS `unit` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `description` text NOT NULL,
  `size_sq_ft` int(11) DEFAULT NULL,
  `size_acres` float DEFAULT NULL,
  `price` float DEFAULT NULL,
  `rental_price` float DEFAULT NULL,
  `on_application` tinyint(1) DEFAULT NULL,
  UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='Stores data for property units' AUTO_INCREMENT=5;

--
-- Table structure for table `property_to_unit`
--

CREATE TABLE IF NOT EXISTS `property_to_unit` (
  `property_id` int(11) NOT NULL,
  `unit_id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


--
-- MySQL which produces list of properties
--

SELECT
    P.id AS id,
    P.name AS name,
    P.street AS street,
    P.town AS town,  
    P.postcode AS postcode,  
    P.description AS description,
    P.team_member AS team_member,
    P.pdf AS pdf,
    P.virtual_tour_link AS virtual_tour_link,
    P.date AS date,
    P.archive AS archive,
    PI.name as image,
    P2.image_ids as image_ids,
    L2.location_ids as location_ids,
    U2.unit_ids as unit_ids

FROM property P

-- Get default image and join using property id

LEFT JOIN property_image PI ON PI.id = P.default_image_id

-- Create a list of image_ids from property_image and
-- property_to_property_image tables then join using property_id

LEFT JOIN (

    SELECT
        property_id,
        GROUP_CONCAT(CAST(id AS CHAR)) as image_ids
    FROM property_to_property_image PTPI
    LEFT JOIN property_image PI ON PI.id = PTPI.property_image_id
    GROUP BY property_id

) P2 ON P2.property_id = P.id

-- Create a list of locations from property_location table
-- and join using property_id

LEFT JOIN (
    SELECT
        property_id,
        property_location_id,
        GROUP_CONCAT(CAST(property_location.id AS CHAR)) AS location_ids
    FROM property_to_property_location
    INNER JOIN property_location ON property_location.id = property_to_property_location.property_location_id
    GROUP BY property_id
) L2 ON L2.property_id = P.id

-- Create a list of units from unit table
-- and join using property_id

LEFT JOIN (
    SELECT
        property_id,
        unit_id,
        GROUP_CONCAT(CAST(unit_id AS CHAR)) AS unit_ids
    FROM property_to_unit
    INNER JOIN unit ON unit.id = property_to_unit.unit_id
    GROUP BY property_id
) U2 ON U2.property_id = P.id

--
-- MySQL which produces list of units
--

SELECT 
id,
name,
description,
size_sq_ft,
size_acres,
price,
rental_price,
on_application,
tenure_ids,
tenure_names,
type_ids,
type_names
FROM unit AS U

-- join tenure ids and names

LEFT JOIN (

    SELECT
        unit_id,
        GROUP_CONCAT( CAST(UT.id AS CHAR) ) AS tenure_ids,
        GROUP_CONCAT(UT.name) AS tenure_names
    FROM unit_to_unit_tenure UTUT
    INNER JOIN unit_tenure UT ON UT.id = UTUT.unit_tenure_id
    GROUP BY unit_id

) UT ON UT.unit_id = U.id

-- join type ids and names

LEFT JOIN (

    SELECT
        unit_id,
        GROUP_CONCAT( CAST(UTYPE.id AS CHAR) ) AS type_ids,
        GROUP_CONCAT(UTYPE.name) AS type_names
    FROM unit_to_unit_type UTUT
    INNER JOIN unit_type UTYPE ON UTYPE.id = UTUT.unit_type_id
    GROUP BY unit_id

) UTYPE ON UTYPE.unit_id = U.id

WHERE 0=0

我目前正在使用附加到每个MySQL查询的动态创建的WHERE语句来过滤属性和单位结果。

2 个答案:

答案 0 :(得分:1)

您的情况需要在属性表中发布外键。将unit_id存储在属性表中,并在查询中使用连接,例如:

select * from property p, unit u
where p.unit_id = u.id
and p.town = ....

编辑:所以我刚刚注意到你的其余SQL。如果您需要保留单元的多对多关系表 - >属性关系然后你需要加入该表的单位和财产。

答案 1 :(得分:1)

你让它变得有点复杂。如果我理解正确,您可以在单个查询中轻松完成此操作。这将搜索具有特定单位期限id的单位的属性:

select * 
from property p 
where p.id in (
    select pu.property_id
    from property_to_unit pu
        inner join unit u ON pu.unit_id = u.id
        inner join unit_to_unit_tenure uut ON u.id = uut.unit_id
    where uut.id = <cfqueryparam value="#uutid#">
)

使用两个查询然后循环以交叉检查声音,因为它可能是狗慢。