MySQL 来自 3 个表的多个联接

MySQL Multiple Joins from 3 Tables

我需要 select 来自 assets_tbl (A) 的所有记录。在这些记录中,我需要有任何灯箱 (lightbox_name) 链接到 asset_id 来自 assets_tbl,其中 author = "scott@co.com"authorized_viewers 包括 "scott@co.com"

我认为这接近我的需要,但它 returns 同一记录的多行:

SELECT
  A.*,
  C.lightbox_name,
  C.author,
  C.authorized_viewers
FROM
  media_tbl A
  LEFT JOIN lightbox_assets_tbl B ON A.asset_id = B.asset_id
  LEFT JOIN lightboxes_tbl C 
    ON B.lightbox_id = C.id
    AND C.author = "scott@co.com"
  LEFT JOIN lightboxes_tbl D ON D.authorized_viewers LIKE "scott@co.com"
ORDER BY A.id DESC

这是表格:

lightboxes_tbl
+-----+----------------+---------------+---------------------+
|id   |lightbox_name   |author         |authoried_viewers    |
+-----+----------------+---------------+---------------------+
|100  | aircraft-types |scott@co.com   |jon@co.com,aj@co.com |
|101  | maintenance    |nicole@co.com  |jon@co.com           |
|102  | ramp           |nicole@co.com  |scott@co.com         |
+-----+----------------+---------------+---------------------+



lightbox_assets_tbl
+-----+-------------+-------------+---------------+----------+
|id   |lightbox_id  |asset_name   |asset_path     | asset_id |
+-----+-------------+-------------+---------------+----------+
|1    |100          |a321.jpg     |project1/imgs/ | 3700     |
|2    |100          |b757.jpg     |project1/imgs/ | 3444     |
|3    |101          |FlyBy.swf    |project4/imgs/ | 1444     |
|4    |102          |Door_757.swf |project5/imgs/ | 3701     |
+-----+-------------+-------------+---------------+----------+


assets_tbl
+-----+---------------------+-------------------------------------+
|asset_id   |asset_name           | asset_location                |
+-----------+---------------------+-------------------------------+
|3700       |a321.jpg             |Libraries\Library_Media\Images |
|200        |757_Taxi.swf         |Libraries\Library_Media\Images |
|3444       |b757.jpg             |Libraries\Library_Media\Images |
|1444       |FlyBy.swf            |Libraries\Library_Media\Images |
|3701       |Door_757.swf         |Libraries\Library_Media\Images |
+----------+---------------------+--------------------------------+

以下是查询的预期结果:

+-----------+---------------------+-------------------------------+------------------+-------------+------------------------+
|asset_id   |asset_name           | asset_location                |lightbox_name     | author      | authorized_viewers     |
+-----------+---------------------+-------------------------------+------------------+-------------+------------------------+
|3700       |a321.jpg             |Libraries\Library_Media\Images |aircraft-types    |scott@co.com |jon@co.com,aj@co.com    |
+-----------+---------------------+-------------------------------+------------------+-------------+------------------------+
|200        |757_Taxi.swf         |Libraries\Library_Media\Images |NULL              |NULL         |NULL                    |
+-----------+---------------------+-------------------------------+------------------+-------------+------------------------+
|3444       |b757.jpg             |Libraries\Library_Media\Images |aircraft-types    |scott@co.com |jon@co.com,aj@co.com    |
+-----------+---------------------+-------------------------------+------------------+-------------+------------------------+
|1444       |FlyBy.swf            |Libraries\Library_Media\Images |NULL              |NULL         |NULL                    |
+-----------+---------------------+-------------------------------+------------------+-------------+------------------------+
|3701       |Door_757.swf         |Libraries\Library_Media\Images |ramp              |nicole@co.com|scott@co.com            |
+----------+---------------------+--------------------------------+------------------+-------------+------------------------+

SQL Fiddle

谢谢!

我想知道为什么您需要 两个 连接到 lightboxes_tbl table。似乎对 table(别名 D)的第二次引用是不必要的。好像你可以使用 OR.

作为演示,在您的查询中复制谓词:

LEFT JOIN lightboxes_tbl C
       ON B.lightbox_id = C.id
      AND ( C.author = 'scott@co.com'
          OR C.authorized_viewers = 'scott@co.com'
          )

但是考虑到 authorized_user 包含一个逗号分隔列表 (ACCKKK!!!),我怀疑您真的想在逗号分隔列表中查找与某项完全匹配的内容。当前的 LIKE 比较等同于等于比较(对 authorized_viewers 列的全部内容)。您可以添加 '%' 通配符来搜索作为字符串一部分的值...

但这种方法也将匹配包含例如ebscott@co.com,这可能不是你真正想要的。

您可以使用 FIND_IN_SET 函数在逗号分隔列表中找到完全匹配...

LEFT JOIN lightboxes_tbl C
       ON B.lightbox_id = C.id
      AND ( C.author = 'scott@co.com'
          OR FIND_IN_SET('scott@co.com',C.authorized_viewers)
          )

存储逗号分隔列表是一种 SQL 反模式。我推荐 Bill Karwin 的书:SQL Anti-Patterns: Avoiding the Pitfalls of Database Programming

http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557