【问题标题】:Joining conditionally in MySQL在 MySQL 中有条件地加入
【发布时间】:2012-10-19 06:40:15
【问题描述】:

我有一个名为USERS 的表和一个名为ADDRESSES 的表,还有一个ADDRESS_TYPE 表。每个用户可以有多个地址。

SELECT *
FROM USER
INNER JOIN address ON address.userId = user.userId
INNER JOIN address_type ON address_type.id = address.addressType
WHERE addressType = 4 
    OR primaryAddress = 1

如果 addressType 为 4,我想将地址表加入用户表,但如果他们的 addressType 不是 4,它应该拉入标记为主要的地址。基本上问题是我需要对查询进行分组,以便每个用户只获得 1 行,同时具有逻辑 =“如果 addressType = 4,加入这个地址,否则如果 primaryAddress = 1,加入这个另一个地址”。

希望这是有道理的,非常感谢任何帮助。

编辑:这些是我正在处理的表格:

用户表

+--------+-----------------+-----------------+ |用户名 |名字 |姓氏 |
+--------+-----------------+-----------------+
| 10001 |黛比 |巴松 |
| 10002 |巴马瓦马 |九冬 |
| 10003 |杰西卡M |史蒂夫 |
| 10004 |金农 |白色 |
+--------+-----------------+-----------------+



地址类型
+----+------+-------------+------------+--------- --+
|编号 |代码 |描述 |可修改 |数据状态 |
+----+------+-------------+------------+--------- --+
| 1 |主页 |主页 | 1 | 1 |
| 2 |布斯 |商业 | 1 | 1 |
| 3 | SCH |学校 | 1 | 1 |
| 4 |唐 |捐赠者地址 | 1 | 1 |
+----+------+-------------+------------+--------- --+

地址表

+----------------+--------+----------- --+-------------+--------------+
|主地址 |用户名 |街道1 |城市|地址类型 |
+----------------+--------+----------- --+-------------+--------------+
| 0 | 10001 | 12660 皮卡特广场|圣地亚哥 | 1 |
| 0 | 10001 |威尔希尔大街 446 号 |富乐顿 | 2 |
| 0 | 10001 | 4224 E. 114 路 |桑顿 | 3 |
| 1 | 10001 |科罗拉多大道 828 号|洛杉矶 | 4 |
| 0 | 10002 | 40A 林登大道,#2 |萨默维尔 | 1 |
| 0 | 10002 | 446 37 街,#2 |奥克兰 |空|
| 1 | 10002 |邮政信箱 06562 |芝加哥 |空|
| 0 | 10002 | 1281 W. 2nd St. |圣佩德罗 |空|
| 1 | 10003 | 10557 S.奥克利大道。芝加哥 |空|
| 0 | 10003 | 1425 哈里森街,#324 |奥克兰 |空|
+----------------+--------+----------- --+-------------+--------------+

【问题讨论】:

  • 您遗漏了一些信息,最好通过向我们展示您的表格的外观来解决这些信息。 (例如,addressType 驻留在哪个表中,primaryAddress 驻留在哪个表中。没有这些信息也可以回答,但这对我们来说是一个不必要的难题
  • 如果您不打算对 ADDRESS_TYPE 进行任何更改,那么您可能需要考虑将地址类型作为 ENUM 放入 ADDRESSES 中
  • “primaryAddress”是否位于“address_type”表中?

标签: mysql sql if-statement group-by conditional


【解决方案1】:

这是你要找的吗?

SELECT *
FROM USER
INNER JOIN address ON address.userId = user.userId
INNER JOIN address_type ON address_type.id = address.addressType
WHERE addressType = 4 
OR NOT EXISTS
(SELECT addressType FROM USER
 INNER JOIN address ON address.userID = user.userID
 INNER JOIN address_type ON address_type.id = address.addressType
 WHERE addressType = 4)
AND primaryAddress = 1

【讨论】:

    【解决方案2】:

    就像其他答案所说,MySQL 确实支持 IF,但我觉得在这种情况下这是错误的方法。我的感觉是左连接可能更合适。

    我认为这应该能让你走到一半,但我需要知道“这个其他地址”来自哪里才能完成查询:

    SELECT
      *
    FROM
      user
    LEFT JOIN
      address ON (address.userId = user.userId AND address.addressType = 4)
    

    (ps.address_type 表似乎有点多余,所以我在连接中跳过它,但也许它很重要?)

    【讨论】:

    • 我可能是错的,但是这里返回的地址永远不会返回 primaryAddress=1 匹配,只有具有 addressType=4 的行
    【解决方案3】:

    MySQL 具有IF 功能(以及更多功能):

    SELECT *,
           IF(addressType = 4, chosen_table.address_field_name, alternative_table.address_field_name) AS field_name
    

    address_field_name 替换为地址字段的名称两次。 chosen_tableIF 的“真”块,alternative_table 是“假”块。

    【讨论】:

      【解决方案4】:

      您尝试过类似 UNION 选择的方法吗?

      可能是这样的:

      SELECT *
      FROM user, address, address_type 
      WHERE address.userId = user.userId
      AND address_type.id = address.addressType
      AND addressType = 4 
      UNION
      SELECT *
      FROM user, address, address_type 
      WHERE address.userId = user.userId
      AND address_type.id = address.addressType
      AND primaryAddress = 1
      

      不确定我的表格结构是否正确.. 但基本点是尝试使用 UNION 语句:-)

      【讨论】:

        【解决方案5】:

        我会删除 ADDRESS_TYPE 表并使您的 ADDRESS 表成为用户地址表,其中您有足够的列来支持 2 或 3 个地址。这样你就不会弄乱你的主用户表。

        没有人会需要超过 2 个地址(下文注明的例外情况除外)。你失去了连接和复杂性,那么你只需要拥有应用程序逻辑来做你想做的事。按照您的设计方式,您可以让这些表格上的每个操作都变得比只有一张表格时更复杂。

        我能看到你上面描述的方式的唯一方法是,如果这是一种面向商业用户的应用程序,他们可以有多个位置可以运送到。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-11-28
          • 1970-01-01
          • 2012-06-04
          • 2020-07-20
          • 1970-01-01
          • 2020-03-18
          • 1970-01-01
          相关资源
          最近更新 更多