我想选择所有类别,子类别并计算属于子类别的业务数量。这是我正在使用的SQl查询。
SELECT
c.id,
c.name,
c.slug,
sc.id,
sc.name,
sc.slug,
COUNT(bsc.id) AS business_count
FROM
fi_category c
LEFT JOIN
fi_subcategory sc ON c.id = sc.category_id AND (sc.deleted_at IS NULL)
LEFT JOIN
fi_business_subcategory bsc ON sc.id = bsc.subcategory_id AND (bsc.deleted_at IS NULL)
WHERE
(c.deleted_at IS NULL)
GROUP BY
c.id, sc.id
然而,我想要做的更多,business_count应该根据他们所属的城市进行过滤,即最后我想要选择所有类别,子类别但是business_count应该有一个像WHERE city.id = 1
这样的子句,对于这个我我想我必须使用count作为子查询,这是我无法弄清楚的。
以下是从fi_business_subcategory
到fi_city
的关系结构。
1)fi_business_subcategory
+----+----------------+-------------+
| id | subcategory_id | business_id |
+----+----------------+-------------+
2)fi_business
+----+---------+-----------+
| id | name | suburb_id |
+----+---------+-----------+
3)fi_suburb
+-----+--------+---------+
| id | name | city_id |
+-----+--------+---------+
4)fi_city
+----+--------+
| id | name |
+----+--------+
我试过这样的事情,但这似乎不起作用
SELECT
c.id,
c.name,
c.slug,
sc.id,
sc.name,
sc.slug,
bsc.business_count
FROM
fi_category c
LEFT JOIN
fi_subcategory sc ON c.id = sc.category_id AND (sc.deleted_at IS NULL)
LEFT JOIN (
SELECT
COUNT(business_id) t1.business_count, t1.subcategory_id
FROM
fi_business_subcategory t1
LEFT JOIN
fi_business t2 ON t2.id = t1.business_id
LEFT JOIN
fi_suburb t3 ON t3.id = t2.suburb_id
LEFT JOIN
fi_city t4 ON t4.id = t3.city_id
WHERE
t4.id = 1
GROUP BY
t1.subcategory_id
) bsc ON sc.id = bsc.subcategory_id AND (bsc.deleted_at IS NULL)
WHERE
(c.deleted_at IS NULL)
GROUP BY
c.id, sc.id
我应该如何构建查询以实现我想要的目标?
答案 0 :(得分:2)
我认为你不应该使用子查询。我相信您只需将fi_business
和fi_business_subcategory
合并为一个带括号的表格因子。
SELECT
c.id,
c.name,
c.slug,
sc.id,
sc.name,
sc.slug,
COUNT(bsc.id) AS business_count
FROM
fi_category c
LEFT JOIN
fi_subcategory sc ON c.id = sc.category_id AND (sc.deleted_at IS NULL)
LEFT JOIN (
fi_business b
INNER JOIN
fi_business_subcategory bsc ON b.id = bsc.business_id AND (bsc.deleted_at IS NULL)
INNER JOIN
fi_suburb su ON su.id = b.suburb_id AND su.city_id = 1
) ON sc.id = bsc.subcategory_id
WHERE
(c.deleted_at IS NULL)
GROUP BY
c.id, sc.id
我checked这是您的表结构的有效SQL。我想即使你的小提琴不包含任何数据,它也会产生预期的结果。有关在联接中可以使用括号的位置的详细信息,请参阅the manual on JOIN syntax。
您可能也会问自己是否真的需要所有联接才能保留联接。使用内连接编写内容会容易得多。
当连接从左向右执行时,您可以先执行内连接,然后执行一系列右连接。这避免了括号:
SELECT
c.id cat_id,
c.name cat_name,
c.slug cat_slug,
sc.id sub_id,
sc.name sub_name,
sc.slug sub_slug,
COUNT(bsc.id) AS business_count
FROM
fi_business b
INNER JOIN
fi_business_subcategory bsc ON b.id = bsc.business_id
AND (b.deleted_at IS NULL) AND (bsc.deleted_at IS NULL)
INNER JOIN
fi_suburb su ON su.id = b.suburb_id AND su.city_id = 1
RIGHT JOIN
fi_subcategory sc ON sc.id = bsc.subcategory_id
RIGHT JOIN
fi_category c ON c.id = sc.category_id AND (sc.deleted_at IS NULL)
WHERE
(c.deleted_at IS NULL)
GROUP BY
c.id, sc.id
答案 1 :(得分:2)
如果您想使用子查询,那么使用尽可能小的变化来表达第二个查询的正确方法是:
SELECT
c.id,
c.name,
c.slug,
sc.id,
sc.name,
sc.slug,
IFNULL(bsc.business_count, 0)
-- turn NULL from left join into 0
FROM
fi_category c
LEFT JOIN
fi_subcategory sc ON c.id = sc.category_id AND (sc.deleted_at IS NULL)
LEFT JOIN (
SELECT
COUNT(*) business_count, t1.subcategory_id
-- removed table name from alias name,
-- and improved performance by simply counting rows
FROM
fi_business_subcategory t1
LEFT JOIN
fi_business t2 ON t2.id = t1.business_id
LEFT JOIN
fi_suburb t3 ON t3.id = t2.suburb_id
LEFT JOIN
fi_city t4 ON t4.id = t3.city_id
WHERE
t4.id = 1 AND (t1.deleted_at IS NULL)
-- check deletion in subquery for performance
GROUP BY
t1.subcategory_id
) bsc ON sc.id = bsc.subcategory_id
-- no longer need to check deletion here
WHERE
(c.deleted_at IS NULL)
GROUP BY
c.id, sc.id
小提琴here。
答案 2 :(得分:1)
试试这个
select
c.id,
c.name,
count(sc.name) as Count
from fi_category as c
left join fi_subcategory as sc on sc.category_id = c.id
left join fi_business_subcategory as fbs on fbs.subcategory_id = sc.id
inner join (
select
fb.name,
fs.id,
fs.city_id
from fi_business as fb
inner join fi_suburb as fs on fs.id = fb.suburb_id
where fs.city_id = 1
) as fb on fb.id = fbs.business_id
group by c.id