【问题标题】:Improved way for multi-table SQL (MySQL) query?多表 SQL (MySQL) 查询的改进方法?
【发布时间】:2013-02-22 14:02:12
【问题描述】:


希望你能提供帮助。我有三个表,并想创建一个条件查询,以根据一个表中存在的行创建一个子集,然后从结果中排除该行,然后查询最终的第三个表。我认为这很简单,但是我在 SQL 方面没有很好的实践,并且在对左连接、相关子查询等进行了 6 个小时的研究/测试之后,它有所帮助,但我仍然无法达到正确的结果集.设置如下:

T1
arn_mkt_stn
A00001_177_JOHN_FM
A00001_177_BILL_FM
A00001_174_DAVE_FM
A00002_177_JOHN_FM
A00006_177_BILL_FM
A00010_177_JOHN_FM
- 注意:名称与 3 位前缀的关系(例如 _177)和 FM 部分始终是一致的:“_177_JOHN_FM”只有 A000XX 发生变化

T2
arn_mkt
A00001_105
A00001_177
A00001_188
A00001_246
A00002_177
A00003_177
A00004_026
A00004_135
A00004_177
A00006_177
A00010_177


示例:因此,如果 _177_JOHN_FM 是 T1 中 arn_mkt_stn 行的子字符串,则在从 T2 获取具有子字符串 177 的 arn_mkts 时将其排除 - 在这种情况下,所需的结果集将是:
A00003_177
A00004_177
A00006_177

同样,_177_BILL_FM 会返回:
A00002_177
A00003_177
A00004_177
A00010_177


然后我想使用这个结果集从基于“A00003”等的第三个表中提取记录
T3
阿恩
A00001
A00002
A00003
A00004
A00005
A00006
...

我尝试了多种方法 [这里 $stn_code = JOHN_FM 和 $stn_mkt = 177]
“从 T2、T1 中选择 * arn!= SUBSTRING(T1.arn_mkt_stn, 1,6)
AND SUBSTRING(T1.arn_mkt_stn, 12,7) = '$stn_code'
AND SUBSTRING(arn_mkt, 8,3) = '$stn_mkt'
(然后使用此结果查询 T3..)

还有一个左连接和一个子查询,但我显然遗漏了一些东西! 收到任何指点,谢谢,

丰富。

[编辑:感谢您帮助 sgeddes。我将在上面扩展我的逻辑......首先,所需的结果集总是与每个查询只有一个名称相关,例如从 T1,让我们使用 JOHN_FM。在 T1 中,JOHN_FM 当前与“arn”相关联(在 arn_mkt_stn 中):A00001、A00002 和 A00010。 T2 中的下一步是查找所有具有 JOHN_FM 的 3 位前缀 (177) 的“arn(在 arn_mkt 内)”,然后排除 T1 中的那些。注意:A00006 仍然存在,因为它没有连接到 T1 中的 JOHN_FM。 BILL_FM 的相同查询给出了稍微不同的结果,不包括 A00001 和 A00006,因为它在 T1 中有这个关联。谢谢,R]

【问题讨论】:

    标签: sql left-join correlated-subquery multi-query


    【解决方案1】:

    您可以使用LEFT JOIN 从 T2 中删除与 T1 中的记录匹配的记录。但是,我不确定我是否理解您的逻辑。

    你说A00001_177_JOHN_FM应该返回:

    A00003_177
    A00004_177
    A00006_177
    

    但是,A00006_177_BILL_FM 不会从上述结果中排除A00006_177 吗?

    如果我对您的理解正确的话,这个查询应该接近(不完全确定您需要返回哪些字段)您正在寻找的内容:

    SELECT T2.arn_mkt, T3.arn
    FROM T2 
      LEFT JOIN T1 ON
        T1.arn_mkt_stn LIKE CONCAT(T2.arn_mkt,'%')
      INNER JOIN T3 ON
        T2.arn_mkt LIKE CONCAT(T3.arn,'%')
    WHERE T1.arn_mkt_stn IS NULL
    

    Sample Fiddle Demo

    --编辑--

    查看 cmets,这应该是您要查找的内容:

    SELECT *
    FROM T2 
      LEFT JOIN T1 ON
        T1.arn_mkt_stn LIKE CONCAT(LEFT(T2.arn_mkt,LOCATE('_',T2.arn_mkt)),'%') AND T1.arn_mkt_stn LIKE '%JOHN_FM'
      INNER JOIN T3 ON
        T2.arn_mkt LIKE CONCAT(T3.arn,'%')
    WHERE T1.arn_mkt_stn IS NULL 
    

    这是更新后的小提琴:http://sqlfiddle.com/#!2/3c293/13

    【讨论】:

    • 非常感谢 sgeddes!反应也快。我已经编辑了我的原始帖子,希望让我的逻辑更清楚一些。非常感谢您的示例。 R
    • @richkoru -- 这就是你要找的东西 (sqlfiddle.com/#!2/3c293/7)?它留下 A0001 因为它们与不同的前缀(不是 177)相关联。希望这会有所帮助。
    • 谢谢!它非常接近。 A00001 应该被排除在外,因为它与 T1 中的 JOHN_FM 相关联。我将对此进行修改以排除 A00001 和 RHS 结果集中的 dups...
    • @richkoru -- 所以 177 无关紧要?例如,它不包括 A00001_177 但不包括 A00001_105。因此 A00001 出现在结果中的原因。
    • @richkoru -- 我已经用我认为你想要的东西更新了我的答案:) 祝你好运。
    猜你喜欢
    • 1970-01-01
    • 2019-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多