2016-07-12 5 views
0

Ich habe diese Anfrage:Wie nur eine von jedem Wert in einer Spalte bekommen

SELECT 
    r.rev_id, rs.name, COUNT(ws.user_id) as likes 
FROM 
    Reviews AS r 
LEFT JOIN 
    Wasliked AS ws ON r.rev_id = ws.rev_id 
LEFT JOIN 
    Restaurants AS rs ON rs.rid = r.rest_id 
GROUP BY 
    rs.name, r.rev_id 
ORDER BY 
    likes DESC 

und das Ergebnis ist:

rev_id name likes 
------------------------ 
    7  rest1  5 
    10  rest1  3 
    6  rest1  2 
    2  rest3  2 
    1  rest2  2 
    5  rest3  1 
    8  rest4  1 

Aber ich mag das Ergebnis so sein:

rev_id name likes 
-------------------------- 
    7  rest1  5 
    2  rest3  2 
    1  rest2  2 

die 3 höchsten Ergebnisse mit verschiedenen Namen.

Ich habe bereits versucht, nur group by rs.name anstelle von rs.name,r.rev_id, aber das verursacht einen Fehler.

Vielen Dank im Voraus

Antwort

0

So möchten Sie den Top-Wert für jeden Namen, begrenzt auf drei Zeilen. Dies legt nahe, row_number():

SELECT TOP 3 rev_id, name, likes 
FROM (SELECT r.rev_id, rs.name, COUNT(ws.user_id) as likes, 
      ROW_NUMBER() OVER (PARTITION BY rs.name ORDER BY COUNT(ws.user_id)) as seqnum 
     FROM Reviews r left join 
      Wasliked ws 
      on r.rev_id = ws.rev_id left join 
      Restaurants rs 
      on rs.rid = r.rest_id 
     GROUP BY rs.name, r.rev_id 
    ) x 
WHERE seqnum = 1 
ORDER BY likes desc; 
+0

Es funktioniert immer noch nicht, zeigt falsche Ergebnisse mit dem gleichen Namen – orestiskim

0

Auch können Sie es so tun, wenn Sie nichts dagegen haben eine redundante SQL schreiben:

select top 3 t1.* 
from ( 
    select r.rev_id, rs.name, count(ws.user_id) as likes 
    from reviews as r 
    left join wasliked as ws on r.rev_id=ws.rev_id 
    left join restaurants as rs on rs.rid=r.rest_id 
    group by rs.name,r.rev_id 
) t1 
inner join (
    select name, max(likes) as likes 
    from (
     select r.rev_id, rs.name, count(ws.user_id) as likes 
     from reviews as r 
     left join wasliked as ws on r.rev_id=ws.rev_id 
     left join restaurants as rs on rs.rid=r.rest_id 
     group by rs.name,r.rev_id) tmp 
    group by name 
) t2 on t1.name = t2.name and t1.likes = t2.likes 
order by t1.likes desc 

@Gordon Linoff Antwort ist ein besserer Weg, dies zu tun, seine SQL genau richtig, und man konnte es gibt Ihnen die niedrigsten likes Zeile pro name finden, also, wenn Sie ändern

ROW_NUMBER() OVER (PARTITION BY rs.name ORDER BY COUNT(ws.user_id)) as seqnum 

zu

ROW_NUMBER() OVER (PARTITION BY rs.name ORDER BY COUNT(ws.user_id) DESC) as seqnum 

es wird Ihnen das richtige Ergebnis geben.

0

Ihre Anfrage hat die Form Zeilen mit max (foo) anzeigen. Die erste Angriffslinie ist Group By, aber manchmal möchten Sie mehr Informationen über das Aggregat. In diesem Fall berechnet hat mag von rev_id und Name, möchten Sie nur die Zeilen mit max (gefällt) für jeden Namen. Das erfordert einen Existenztest:

with T (rev_id, name, likes) as (
    SELECT r.rev_id, rs.name, COUNT(ws.user_id) as likes 
    FROM Reviews as r 
    left join Wasliked as ws on r.rev_id=ws.rev_id 
    left join Restaurants as rs on rs.rid=r.rest_id 
    GROUP BY rs.name,r.rev_id 
) 
select * from T as L 
where exists (
     select 1 from T 
     where name = L.name 
     group by name 
     having max(likes) = L.likes 
) 
order by likes desc 

Das ist ungefähr richtig.

Ich bevorzuge meine Version zu den anderen bisher zur Verfügung gestellt. Es verwendet nicht die nicht standardmäßige Formel top N, und die Abfrage wird in Bezug auf die logische Operation, die Sie benötigen, d. H. Quantifizierung, ausgeführt.

Mit der Praxis wird where exists einfacher, und Sie sparen viele komplizierte Abfragen.