如何使用两个必需参数和一个可选参数连接两个表?

时间:2015-03-06 21:44:11

标签: mysql sql

如果这是相当基本的MySQL,我道歉,但我不知所措。我有两个表:usersus_geolocations,我想创建一个用户地理位置视图。

我的第一个问题是,我lat中的某些城市(甚至是某些邮政编码)有多个longus_geolocations条目。我的第二个问题是我在zip表格中将users作为可选参数。

我希望获得包含所有不同citystateziplatlong值的视图,其中{{ 1}}和city位于state表中。

我现在拥有的是:

users

但当CREATE VIEW `active_us_geolocations` AS SELECT DISTINCT `users`.`city` AS `city`, `users`.`state` AS `state`, `users`.`zip` AS `zip`, `us_geolocations`.`lat` AS `lat`, `us_geolocations`.`long` AS `long` FROM (`users` LEFT JOIN `us_geolocations` ON (((`users`.`city` = `us_geolocations`.`city`) AND (`users`.`state` = `us_geolocations`.`state`) #Only if there is a `users`.`zip` AND (`users`.`zip` = `us_geolocations`.`zip`)))) 中的zip为空时,我也会变空userslat

我是否需要将所需参数和可选参数分隔到自己的查询中,或者是否可以在特定类型的连接中执行这些操作?如果它确实需要在不同的部分,我将如何指定?

4 个答案:

答案 0 :(得分:2)

CREATE VIEW `active_us_geolocations` AS
    SELECT DISTINCT
        `users`.`city` AS `city`,
        `users`.`state` AS `state`,
        `users`.`zip` AS `zip`,
        `us_geolocations`.`lat` AS `lat`,
        `us_geolocations`.`long` AS `long`
    FROM
        (`users`
        LEFT JOIN `us_geolocations` 
            ON (((`users`.`city` = `us_geolocations`.`city`)
            AND (`users`.`state` = `us_geolocations`.`state`)
WHERE `users`.`zip` IS NOT NULL

答案 1 :(得分:2)

这是你要找的吗?

CREATE VIEW `active_us_geolocations` AS
    SELECT DISTINCT
        `users`.`city`           AS `city`,
        `users`.`state`          AS `state`,
        `users`.`zip`            AS `zip`,
        `us_geolocations`.`lat`  AS `lat`,
        `us_geolocations`.`long` AS `long`
    FROM
        `users`
    LEFT JOIN
        `us_geolocations`
    ON
             `users`.`city`  = `us_geolocations`.`city`
        AND  `users`.`state` = `us_geolocations`.`state`
        AND (`users`.`zip`   = `us_geolocations`.`zip`
        OR   `users`.`zip` IS NULL
        OR   `users`.`zip = '')

修改

上面的解决方案通过确保城市和州匹配,然后检查zip是否存在,通过匹配用户地址和纬度/经度值来选择所有活动的城市/州/邮政/纬度/长组合。 / p>

如果城市和州匹配与zip匹配,则可能希望将用户地址与lat / long值匹配。这是一个略有不同的查询,如下所示:

CREATE VIEW `active_us_geolocations` AS
    SELECT DISTINCT
        `users`.`city`           AS `city`,
        `users`.`state`          AS `state`,
        `users`.`zip`            AS `zip`,
        `us_geolocations`.`lat`  AS `lat`,
        `us_geolocations`.`long` AS `long`
    FROM
        `users`
    LEFT JOIN
        `us_geolocations`
    ON
            `users`.`city`  = `us_geolocations`.`city`
        AND `users`.`state` = `us_geolocations`.`state`
        OR  `users`.`zip`   = `us_geolocations`.`zip`

答案 2 :(得分:1)

看起来你在SQL代码中有一些很好的答案,考虑到你的SQL结构(我还没有尝试过任何一个,所以只是说一目了然而且不知道你的数据结构是什么样的,他们好看)。

您可能还会考虑以下两种替代解决方案/想法之一:

  1. 如果您是编写数据库代码/创建数据库结构的人,则可以考虑更高级别的规范化。这应该使不同数据的比较分离更加清晰。 我的意思是,不是让两个表中的邮政编码值都在一个表中,而是在它们之间创建一个链接表(规范化,归结,很大程度上不会复制数据)。 这使得RDBMS的关系部分更容易,因为基础数学依赖于数据的唯一性,因此数据库系统可以更有效地实现数据关系。

  2. 如果此查询支持您可以使用的应用程序,请考虑将查询的条件组件放在应用程序端并使视图成为更通用的结构(尽管如果您的数据库结构更加规范化了左侧)加入仍然很可能会解决导致你问题的原因。)

  3. 希望有所帮助,但以下是关于normalization&的几个链接。 surrogate keys

    此外,有关第1点的更多详情:
    通过这种方式,您将拥有两个以上的表来保存数据。事实上,如果这是我创建的数据库,我会创建一个位置表(或一组表,记住试图避免每个部分的重复,尽可能合理)和与geolocation的链接,因为你是使用纬度和经度作为地理位置的经度...并且取决于lat& long(例如,如果您的纬度和纵向坐标可以包含多个地址)。 如果您跟踪的坐标非常精确,一个坐标代表一个地址,那么地址表和地理位置表应该是同一个表。虽然一个城市应该在它自己的餐桌旁。

答案 3 :(得分:0)

这可能对您有用:

...
LEFT JOIN `us_geolocations` 
  ON users.city=us_geolocations.city
    AND users.state=us_geolocations.state
    AND (users.zip IS NULL OR users.zip=us_geolocations.zip)