我必须提供一个活动的,具有一个或多个域,并且其所有域都被删除的不同站点的列表。到目前为止,这是我的查询。
SELECT DISTINCT *
FROM sites JOIN domains ON domains.site = sites.id
WHERE domains.is_deleted = 1 AND sites.is_deleted = 0
从我的研究中,检查网站是否有多个域的最佳方法似乎是拥有COUNT()
子查询。如何使用COUNT()
计算每个网站的域数?
这是 SQL fiddle 。
答案 0 :(得分:2)
获取每个网站符合条件的域名数量:
SELECT DISTINCT sites.id,
sites.name,
COUNT(domains.id) AS DomainCount
FROM sites
INNER JOIN domains ON domains.site = sites.id
WHERE domains.is_deleted = 1
AND sites.is_deleted = 0
GROUP BY sites.id,
sites.name
和karina说的一样,以下查询只会显示包含多个域的网站:
SELECT DISTINCT sites.id,
sites.name
FROM sites
INNER JOIN domains ON domains.site = sites.id
WHERE domains.is_deleted = 1
AND sites.is_deleted = 0
GROUP BY sites.id,
sites.name
HAVING COUNT(domains.id) > 1
答案 1 :(得分:1)
一种方法使用LEFT JOIN
找不到匹配项:
SELECT s.*
FROM sites s LEFT JOIN
domains d
ON d.site = s.id AND
d.is_deleted <> 1
WHERE s.is_deleted = 0 AND d.site IS NULL;
注意:这将返回没有域名的网站。这些技术符合您的要求。这也假定is_deleted
永远不会NULL
(如果NULL
是可能的话,很容易改变逻辑。)
编辑:
哎呀,我看到你确实想要一个或多个域名。在这种情况下,我会选择EXISTS
和NOT EXISTS
:
SELECT s.*
FROM sites s
WHERE s.is_deleted = 0 AND
EXISTS (SELECT 1 FROM domains d WHERE d.site = s.id AND d.is_deleted = 1) AND
NOT EXISTS (SELECT 1 FROM domains d WHERE d.site = s.id AND d.is_deleted <> 1);
EXISTS
和NOT EXISTS
通常比使用COUNT()
的子查询更好(性能方面)。
答案 2 :(得分:1)
问:如何使用COUNT()计算每个网站的域数?
(问题的答案在答案的底部。)
有几个不同的查询将返回指定的结果。
我从
开始构建这样的查询“活跃的不同网站列表”
我们可以从sites表中获取(非null)is_deleted列为0的行...
SELECT s.id
, s.name
, s.company
, s.association
, s.is_supercharged
, s.is_deleted
FROM sites s
WHERE NOT s.is_deleted
ORDER BY s.id
“谁拥有一个或多个域名”
我们可以编写一个查询,从域表中返回站点(FK)列的值列表
SELECT d.site
FROM domain d
GROUP BY d.site
“并且其所有域名都已删除”
我们可以编写另一个查询,该查询从域中具有is_deleted = 0的行的站点列返回不同的值列表
SELECT a.site
FROM domain a
WHERE NOT a.is_deleted
GROUP BY a.site
我们可以把这三个问题放在一起。我们可以将最后两个查询转换为内联视图(在parens中包装并引用它们就像它们是表格一样。)我们可以使用内部联接(具有至少一个域的站点)来仅获取至少具有一个域的站点。并使用反连接模式(具有活动域的站点),以排除具有活动域的站点。
例如:
SELECT s.id
, s.name
, s.company
, s.association
, s.is_supercharged
, s.is_deleted
FROM sites s
JOIN ( SELECT d.site AS site_id
FROM domain d
GROUP BY d.site
) r
ON r.site_id = s.id
LEFT
JOIN ( SELECT a.site AS site_id
FROM domain a
WHERE NOT a.is_deleted
GROUP BY a.site
) q
ON q.site_id = s.id
WHERE q.site_id IS NULL
AND NOT s.is_deleted
ORDER BY s.id
这只是将返回指定结果的几种不同查询模式之一。
我们还可以编写这样的查询,以返回不同的网站列表,其中域的“计数”等于被删除的域的“计数”
SELECT d.site
FROM domain d
GROUP BY d.site
HAVING SUM(IF(d.is_deleted,1,0)) = SUM(1)
有了这个,我们可以使用内部联接到站点......
SELECT s.id
, s.name
, s.company
, s.association
, s.is_supercharged
, s.is_deleted
FROM sites s
JOIN ( SELECT d.site AS site_id
FROM domain d
GROUP BY d.site
HAVING SUM(IF(d.is_deleted,1,0)) = SUM(1)
) q
ON q.site_id = s.id
WHERE NOT s.is_deleted
ORDER BY s.id
还有其他几种模式会返回相同的结果。
问:如何使用COUNT()计算每个网站的域数?
要获得至少包含一个域的网站的每个网站的域数,而不考虑该网站本身是否已被删除:
SELECT d.site
, COUNT(1) AS count_domains
FROM domain d
GROUP BY d.site
同样,要为每个网站计算“is_deleted”域名(对于至少包含一个域名的网站)
SELECT d.site
, COUNT(IF(d.is_deleted,1,NULL)) AS count_deleted_domains
FROM domain d
GROUP BY d.site
我们可以合并这些查询,并为网站返回两行计数。
这些查询省略了“计数”零。要获得零计数,并且仅包括不是is_deleted的网站:
SELECT s.id AS `site`
, COUNT(d.site) AS `count_domains`
, COUNT(IF(d.is_deleted,1,NULL)) AS `count_deleted_domains`
FROM site s
LEFT
JOIN domain d
ON d.site = s.id
WHERE NOT s.is_deleted
GROUP BY s.id
ORDER BY s.id
我们还可以在HAVING子句中引用COUNT()聚合的结果。
此查询将返回所有没有“有效”域的网站,包括没有任何相关域的网站。
SELECT s.id AS `site`
, COUNT(d.site) AS `count_domains`
, COUNT(IF(d.is_deleted,1,NULL)) AS `count_deleted_domains`
FROM site s
LEFT
JOIN domain d
ON d.site = s.id
WHERE NOT s.is_deleted
GROUP BY s.id
HAVING COUNT(d.site) = COUNT(IF(d.is_deleted,1,NULL))
ORDER BY s.id
我们可以轻松地修改它以返回指定的站点列表(将对站点表中的列的引用添加到SELECT列表中)并省略SELECT列表中的COUNT()表达式。
如果我们只想要拥有至少一个域的网站,我们可以简单地删除LEFT关键字,使其成为内连接而不是外连接。