我从头开始创建了一个产品/评论系统,我很难在SQL Server中执行以下查询。
我的架构有不同的表格,用于:产品,评论,类别,productPhotos和品牌。我必须查询它们以查找品牌和类别名称,照片详细信息,平均评分和评论数量。
我很难获得评论和平均评分。
可以隐藏(用户已删除)或屏蔽(等待审核)。我的产品表没有评论数或平均评分列,所以我需要在该查询上计算,但不计算被阻止和隐藏的数据(r.bloqueado = 0和r.hidden = 0)。
我有下面的查询,但它计算被阻止和隐藏。如果我取消注释“和r.bloqueado = 0和r.hidden = 0”部分我得到了正确的计数,但是它没有显示有0评论的产品(我需要的东西!)。
select top 20
p.id, p.brand, m.nome, c.name,
count(r.product) AS NoReviews, Avg(r.nota) AS AvgRating,
f.id as cod_foto,f.nome as nome_foto
from
tblBrands AS m
inner join
(tblProducts AS p
left join
tblProductsReviews AS r ON p.id = r.product) ON p.brand = m.id
left join
tblProductsCategorias as c on p.categoria = c.id
left join
(select
id_product, id, nome
from
tblProductsFotos O
where
id = (SELECT min(I.id)
FROM tblProductsFotos I
WHERE I.id_product = O.id_product)) as f on p.id = f.id_product
where
p.bloqueado = 0
//Problem - and r.bloqueado=0 and r.hidden=0
group by
p.id, p.brand, p.modalidade, m.nome, c.name, f.id,f.nome"
需要您的建议:
我见过其他系统在产品表中有平均等级和评论数。这将有助于此查询的复杂性(可能还有性能),但是我必须在每个新的审核,阻止和隐藏操作中执行额外的查询。我可以轻松地做到这一点。考虑到包含和更新比显示产品少得多,这听起来不错。 这样做会更好吗?
或者找到修复此查询的方法更好吗?你能帮我找个解决方案吗?
由于
答案 0 :(得分:0)
为了计算产品的数量你可以使用的情况和总和分配1那里的值不是r.bloqueado = 0或r.hidden = 0和0这些值(所以你可以避免过滤器在哪里)< / p>
"select top 20 p.id, p.brand, m.nome, c.name, sum(
case when r.bloqueado=0 then 0
when r.hidden=0 then 0
else 1
end ) AS NoReviews,
Avg(r.nota) AS AvgRating, f.id as cod_foto,f.nome as nome_foto
from tblBrands AS m
inner join (tblProducts AS p
left join tblProductsReviews AS r ON p.id=r.product ) ON p.brand = m.id
left join tblProductsCategorias as c on p.categoria=c.id
left join (select id_product,id,nome from tblProductsFotos O
where id = (SELECT min(I.id) FROM tblProductsFotos I
WHERE I.id_product = O.id_product)) as f on p.id = f.id_product where p.bloqueado=0
group by p.id, p.brand, p.modalidade, m.nome, c.name, f.id,f.nome"
对于平均可能你可以做类似的事情
答案 1 :(得分:0)
将where子句与外连接组合时,很容易丢失记录。外表中不存在的行将返回NULL。您的过滤器意外地排除了这些空值。
以下是一个展示正在发生的事情的例子:
/* Sample data.
* There are two tables: product and review.
* There are two products: 1 & 2.
* Only product 1 has a review.
*/
DECLARE @Product TABLE
(
ProductId INT
)
;
DECLARE @Review TABLE
(
ReviewId INT,
ProductId INT,
Blocked BIT
)
;
INSERT INTO @Product
(
ProductId
)
VALUES
(1),
(2)
;
INSERT INTO @Review
(
ReviewId,
ProductId,
Blocked
)
VALUES
(1, 1, 0)
;
在没有where子句的情况下连接表的外部返回:
<强>查询强>
-- No where.
SELECT
p.ProductId,
r.ReviewId,
r.Blocked
FROM
@Product AS p
LEFT OUTER JOIN @Review AS r ON r.ProductId = p.ProductId
;
<强>结果强>
ProductId ReviewId Blocked
1 1 0
2 NULL NULL
过滤Blocked = 0
会删除第二条记录,因此会ProductId
2.而是:
-- With where.
SELECT
p.ProductId,
r.ReviewId,
r.Blocked
FROM
@Product AS p
LEFT OUTER JOIN @Review AS r ON r.ProductId = p.ProductId
WHERE
r.Blocked = 0
OR r.Blocked IS NULL
;
此查询保留NULL值,ProductId
2.您的示例稍微复杂一点,因为您有两个字段。
SELECT
...
WHERE
(
Blocked = 0
AND Hidden = 0
)
OR Blocked IS NULL
;
您不需要检查两个字段是否为NULL,因为它们出现在同一个表中。