2016-10-31 3 views
0

Ich habe ein Produkt/Review-System von Grund auf neu erstellt und ich habe eine harte Zeit, um die folgende Abfrage in SQL Server zu tun.Entwerfen und Abfragen von Produkt/Review-System

Mein Schema hat verschiedene Tabellen, für: Produkte, Bewertungen, Kategorien, ProduktFotos und Marke. Ich muss sie alle abfragen, um den Namen der Marke und der Kategorie, die Details der Fotos, die durchschnittliche Bewertung und die Anzahl der Bewertungen zu finden.

Ich habe eine harte Zeit, Anzahl der Bewertungen und durchschnittliche Bewertung zu bekommen.

Bewertungen können ausgeblendet (Benutzer wurde gelöscht) oder blockiert (auf Moderation warten). Meine Produkttabelle hat keine Anzahl von Reviews oder Average Rating-Spalten, also muss ich sie für diese Abfrage zählen, aber nicht die blockierten und versteckten zählen (r.bloqueado = 0 und r.hidden = 0).

Ich habe die Abfrage unten, aber es zählt die blockiert und versteckt. Wenn ich den "und r.bloqueado = 0 und r.hidden = 0" Teil auskommentiere, bekomme ich die richtige Zählung, aber dann zeigt es keine Produkte, die 0 Bewertungen haben (etwas was ich brauche!).

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" 

Ihre Frage:

Ich habe andere Systeme gesehen, die Gesamtwertung und Anzahl der Bewertungen in der Produkttabelle hat. Dies würde sehr viel in der Komplexität dieser Abfrage helfen (wahrscheinlich auch Performance), aber dann muss ich zusätzliche Abfragen in jeder neuen Überprüfung, blockierten und versteckten Aktionen durchführen. Ich kann das leicht machen. Wenn man bedenkt, dass Updates viel weniger enthalten, als die Produkte zu zeigen, klingt das nett. Wäre eine bessere Idee, das zu tun?

Oder ist es besser, einen Weg zu finden, um diese Abfrage zu beheben? Kannst du mir helfen, eine Lösung zu finden?

Dank

Antwort

0

Für die Anzahl der Produkte zählen Sie dann, wenn und Summe zuweisen 1 gibt den Wert r.bloqueado = 0 nicht oder r.hidden = 0 und 0 für diese Werte verwenden können (so können Sie vermeiden, die Filter in den

) konnten
"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" 

für avg Sie Somethings ähnlich tun können

0

Es ist sehr einfach Aufzeichnungen zu verlieren, wenn eine where-Klausel mit einem äußeren Kombination JOIN. Zeilen, die in der äußeren Tabelle nicht vorhanden sind, werden als NULL zurückgegeben. Ihr Filter hat diese Nullen versehentlich ausgeschlossen.

Hier ist ein Beispiel, das, was passiert zeigt:

/* 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) 
; 

Äußere der Tabellen Beitritt ohne where-Klausel, zurückgibt:

Abfrage

-- No where. 
SELECT 
    p.ProductId, 
    r.ReviewId, 
    r.Blocked 
FROM 
    @Product AS p 
     LEFT OUTER JOIN @Review AS r  ON r.ProductId = p.ProductId 
; 

Ergebnis

ProductId ReviewId Blocked 
1   1   0 
2   NULL  NULL 

Filterung für Blocked = 0 würde den zweiten Datensatz entfernen und daher ProductId 2.Statt dessen:

-- 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 
; 

Diese Abfrage behält den NULL-Wert, und ProductId 2. Ihr Beispiel ist ein wenig komplizierter, weil Sie zwei Felder haben.

SELECT 
    ... 
WHERE 
    (
     Blocked = 0 
     AND Hidden = 0 
    ) 
    OR Blocked IS NULL 
; 

Sie müssen nicht beide Felder für NULL zu überprüfen, da sie in der gleichen Tabelle.

+0

Danke! Es hat nicht den ganzen Weg funktioniert. Es berücksichtigt nicht die blockierten in der Zählung, sondern berücksichtigt die versteckten. Ich habe versucht, es herumzukritzeln, aber ich konnte es nicht schaffen. Aber Unterstützung für die erste Frage ... Ist nicht besser, eine Zählung und avg Feld in die Produkttabelle aufzunehmen? Wäre nicht bessere Leistung und lesbarer? Der Kompromiss ist keine große Sache ... nur ein bisschen mehr Codierung ... – mEba

Verwandte Themen