我的架构如下:
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和概念,但我不知所措。
答案 0 :(得分:3)
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
答案 1 :(得分:1)
免责声明:以下解决方案是用MS SQL-Server 2008 TSQL编写的。
我不相信我所做的任何事情在MySQL中都不存在,但如果我使用的任何内容在MySQL中都不合适请告诉我,以便我能够纠正它。如果有人希望编辑和更正MySQL的语法,那么非常欢迎您。我不知道我需要用反引号和诸如此类的东西逃脱,所以我不想尝试它并用正确的MS服务器代码创建糟糕的MySQL代码。
我也不会假装声称我的解决方案高效或优雅,因为我绝不是SQL专家。
该查询使用联接来创建Site + Feature的所有可能组合。然后,它会检查SiteFeature表中是否存在该组合
--table creation
declare @Sites Table(
[Id] int not null,
[Url] varchar(30)
)
INSERT INTO @Sites ([Id],[Url])
VALUES (1,'a.com'),(2,'b.edu'),(3,'c.org')
declare @Features Table(
[Id] int not null,
[Name] varchar(30)
)
INSERT INTO @Features ([Id],[Name])
VALUES (1,'apple'),(2,'banana'),(3,'cherry'),(4,'diaper'),(5,'egg'),(6,'fish')
declare @SiteFeatures Table(
[SiteId] int not null,
[FeatureID] int not null
)
INSERT INTO @SiteFeatures ([SiteId],[FeatureID])
VALUES (1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(2,4),(3,2),(3,3)
--QUERY HERE
SELECT [SiteId], [SiteURL], [FeatureName], [Enabled] =
CASE
WHEN EXISTS
(SELECT *
FROM @SiteFeatures SF
WHERE SF.SiteId = tmp.SiteId
AND SF.FeatureID = tmp.FeatureId)
THEN (1)
ELSE (0)
END
FROM
(SELECT S.Id as [SiteId],
S.Url as [SiteURL],
F.Id as [FeatureId],
F.Name as [FeatureName]
FROM @Sites S
LEFT JOIN @Features F ON (1 = 1)) as tmp
答案 2 :(得分:1)
select s.id,s.url,f.featurename,if(sf.featureid is not null,1,0) as enabled
from features as f
cross join sites as s
left join sitefeatures as sf on sf.siteid = s.id and sf.featureid = f.id
order by s.url,f.featurename;
+----+-------+-------------+---------+
| id | url | 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 | 1 |
| 3 | c.org | diaper | 0 |
| 3 | c.org | egg | 0 |
| 3 | c.org | fish | 0 |
+----+-------+-------------+---------+
18 rows in set (0.00 sec)