数据库
首页 > 数据库> > MySQL,三个表:选择右表中的所有行,包括未在中间表中映射的行

MySQL,三个表:选择右表中的所有行,包括未在中间表中映射的行

作者:互联网

我的架构如下:

Sites S
| S.Id | S.Url |
| 1    | a.com |
| 2    | b.edu |
| 3    | c.org |

SiteFeatures SF
| SF.SiteId | SF.FeatureID |
| 1         | 1            |
| 1         | 2            |
| 1         | 3            |
| 2         | 1            |
| 2         | 2            |
| 2         | 3            |
| 2         | 4            |
| 3         | 2            |
| 3         | 3            |

Features F
| F.Id | F.FeatureName |
| 1    | apple         |
| 2    | banana        |
| 3    | cherry        |
| 4    | diaper        |
| 5    | egg           |
| 6    | fish          |

我想选择映射到所有功能的所有网站,包括中间连接表中缺少的功能.对于在连接表中没有条目的功能,我想显示“0”.对于连接表中存在的功能,我想要一个“1”.

所以结果将如下所示:

| SiteId | SiteURL | FeatureName | Enabled |
| 1      | a.com   | apple       | 1       |
| 1      | a.com   | banana      | 1       |
| 1      | a.com   | cherry      | 1       |
| 1      | a.com   | diaper      | 0       |
| 1      | a.com   | egg         | 0       |
| 1      | a.com   | fish        | 0       |
| 2      | b.edu   | apple       | 1       |
| 2      | b.edu   | banana      | 1       |
| 2      | b.edu   | cherry      | 1       |
| 2      | b.edu   | diaper      | 1       |
| 2      | b.edu   | egg         | 0       |
| 2      | b.edu   | fish        | 0       |
| 3      | c.org   | apple       | 0       |
| 3      | c.org   | banana      | 1       |
| 3      | c.org   | cherry      | 0       |
| 3      | c.org   | diaper      | 1       |
| 3      | c.org   | egg         | 0       |
| 3      | c.org   | fish        | 0       |

– 编辑 –
附加信息.

我最初使用这篇文章创建了一个数据透视表:

http://dev.mysql.com/tech-resources/articles/wizard/print_version.html

基于那篇文章,我写了一个SQL语句来动态生成一个生成数据透视表的SQL查询.

那句话看起来像这样:

SELECT
 CONCAT( ", SUM(IF( F.FeatureName = '" , F.FeatureName , "', 1,0 ))" , " AS `" , F.FeatureName , "` ") AS CutNPaste
FROM
  Features F
WHERE 1
GROUP BY F.FeatureName
ORDER BY F.FeatureName
-- END

第二个SQL语句如下:

SELECT
, S.Url
/* This section was dynamically generated, and copied into this SELECT statement */
, SUM(IF( F.FeatureName = 'apple', 1,0 )) AS `apple`
, SUM(IF( F.FeatureName = 'banana', 1,0 )) AS `banana`
, SUM(IF( F.FeatureName = 'cherry', 1,0 )) AS `cherry`
, SUM(IF( F.FeatureName = 'diaper', 1,0 )) AS `diaper`
, SUM(IF( F.FeatureName = 'egg', 1,0 )) AS `egg`
, SUM(IF( F.FeatureName = 'fish', 1,0 )) AS `fish`
/* END of dynamic part */
FROM
  Sites S
LEFT OUTER JOIN SiteFeatures SF ON S.Id = SF.SiteId
LEFT OUTER JOIN Features F ON SF.FeatureId = F.Id
WHERE 1
AND SF.FeatureId = F.Id
AND S.Enabled = 1
GROUP BY S.Url
-- END

结果看起来像这样:

| Url   | apple | banana | cherry | diaper | egg | fish |
| a.com | 1     | 1      | 1      | 0      | 0   | 0    |
| b.edu | 1     | 1      | 1      | 1      | 0   | 0    |
| c.org | 0     | 1      | 0      | 1      | 0   | 0    |

我试图在这两个语句中重新使用SQL和概念,但我不知所措.

解决方法:

CROSS JOIN可以在这里使用. (第一个查询首先由@nick rulez发布):

SELECT s.Id   AS SiteId 
     , s.Url  AS SiteURL 
     , f.FeatureName 
     , CASE WHEN sf.SiteID = s.Id 
            THEN 1
            ELSE 0
       END AS Enabled
FROM
    Sites AS s
  CROSS JOIN
    Features AS f
  LEFT JOIN
    SiteFeatures AS sf
      ON  sf.SiteID = s.Id
      AND sf.FeatureID = f.Id
SELECT s.Id   AS SiteId 
     , s.Url  AS SiteURL 
     , f.FeatureName 
     , CASE WHEN EXISTS
                 ( SELECT *
                   FROM SiteFeatures AS sf
                   WHERE sf.SiteID = s.Id
                     AND sf.FeatureID = f.Id
                 ) 
            THEN 1
            ELSE 0
       END AS Enabled
FROM
    Sites AS s
  CROSS JOIN
    Features AS f
SELECT s.Id   AS SiteId 
     , s.Url  AS SiteURL 
     , f.FeatureName 
     , ( SELECT COUNT(*)
         FROM SiteFeatures AS sf
         WHERE sf.SiteID = s.Id
           AND sf.FeatureID = f.Id
       ) AS Enabled
FROM
    Sites AS s
  CROSS JOIN
    Features AS f

标签:outer-join,mysql,join
来源: https://codeday.me/bug/20190903/1795242.html