2013-08-21 4 views
5

Ich habe 2 Tabellen: photo und like. Ich versuche, beliebte Fotos basierend auf der Anzahl der Likes an einem Tag zu erhalten. Also im Grunde so etwas wie 'heute populär'.MySQL beliebte Zeilen auf verschiedenen Zeitniveaus

SELECT 
    p.id AS id, COUNT(li.id) AS total_likes \ 
FROM `photo` p \ 
    LEFT JOIN `like` li \ 
    ON p.id = li.photo_id \ 
WHERE 
    li.date > DATE_SUB(CURDATE(), INTERVAL 1 DAY) \ 
GROUP BY \ 
    p.id 

Dies funktioniert gut, wenn es heute genügend Likes gibt. Aber wenn es am vergangenen Tag keine Likes gibt, werden keine Einträge zurückgegeben.

Ich möchte auch ein wenig ändern. Ist es möglich, Levels zu machen? Zum Beispiel:
Rang Fotos basierend auf mehreren Tagen:

1. Get photos based on how many likes today 
2. Get photos based on how many likes for last week 
and so on... 

Also im Grunde, was das bedeutet ist, lassen Sie uns sagen, dass wir 30 Produkte erhalten müssen. Zuerst wird es versuchen, Zeilen zu bekommen, basierend darauf, wie viele Likes es heute gab. Es kann eine beliebige Zahl von 20, 15 usw. sein. Dann wird es die verbleibenden Zeilen erhalten, die benötigt werden, um zu einer Gesamtzahl von 30 zu gelangen, aber wird nun basierend auf wie vielen Likes in einer Woche sortiert.

So something like: 
SELECT FROM photo SORT BY likes today, likes in a week ... 

Vielen Dank für Ihre Hilfe!

+0

ändern wohin und – Strawberry

+0

DDLs und/oder einen sqlfiddle sein könnte helfen – Strawberry

Antwort

3

Sie können verschiedene Zählungen basierend auf CASE berechnen, z. die letzten 30 Tage mit Zählungen für den letzten Tag. letzte Woche und die letzten 30 Tage:

SELECT 
    p.id AS id 
    ,COUNT(CASE WHEN li.DATE > DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN li.id END) AS daily_likes 
    ,COUNT(CASE WHEN li.DATE > DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN li.id END) AS weekly_likes 
    ,COUNT(li.id) AS total_likes 
FROM `photo` p 
JOIN `LIKE` li 
    ON p.id = li.photo_id 
WHERE 
    li.DATE > DATE_SUB(CURDATE(), INTERVAL 30 DAY) 
GROUP BY 
    p.id 
ORDER BY daily_likes DESC, weekly_likes DESC, total_likes DESC 
LIMIT 30 

Ich weiß nicht, auf welcher Definition Ihres Limit auf basiert, könnte es so etwas wie

SELECT * 
FROM 
(
    SELECT 
    p.id AS id 
    ,COUNT(CASE WHEN li.DATE > DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN li.id END) AS daily_likes 
    ,COUNT(CASE WHEN li.DATE > DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN li.id END) AS weekly_likes 
    ,COUNT(li.id) AS total_likes 
    FROM `photo` p 
    JOIN `LIKE` li 
     ON p.id = li.photo_id 
    WHERE 
    li.DATE > DATE_SUB(CURDATE(), INTERVAL 30 DAY) 
    GROUP BY 
    p.id 
) AS dt 
ORDER BY 
    case when daily_likes > 20 then daily_likes else 0 end desc, 
    case when weekly_likes > 100 then weekly_likes else 0 end desc, 
    total_likes DESC 
LIMIT 30 
+0

Das ist sinnvoll. Also setzt dein zweiter Bit Code für die Bestellung Mindestanforderungen für Likes? Oder verstehe ich das falsch? – pewpewlasers

+0

Ihr zweiter Code für die Bestellung funktioniert nicht für mich, es gibt mir eine 'Referenz 'daily_likes' nicht unterstützt (Verweis auf Gruppenfunktion)' Fehler – pewpewlasers

+1

Ja, Sie sind richtig, nur daily_likes> 20 und weekly_likes> 100 verwendet werden. Aber MySQL scheint nicht den Alias ​​in ORDER BY zu unterstützen :-(Meine Antwort geändert, um eine Abgeleitete Tabelle zu verwenden – dnoeth

1

Haben Sie UNION versucht?

technet.microsoft

Techonthenet.com

Wikipedia

und NICHT VORHANDEN

MySQL

Mit UNION Sie wählen mehrere select-Anweisungen beitreten können, so lange die Spalten sind die gleichen

Von der Spitze von meinem Kopf, so etwas wie

(select p.id as id, 
     count(li.id) as total_likes 
    from photo p, 
     like li 
where p.id = li.photo_id 
    and li.date > date_sub(curdate(), interval 1 day) 
    and rownum <= 10 
order by total_likes 
group by p.id) 
union 
(select p.id as id, 
     count(li.id) as total_likes 
    from photo p, 
     like li 
where p.id = li.photo_id 
    and li.date > date_sub(curdate(), interval 7 day) 
    and rownum <= 10 
    and not exists (select p.id as id, 
        count(li.id) as total_likes 
        from photo p, 
          like li 
        where p.id = li.photo_id 
         and li.date > date_sub(curdate(), interval 1 day) 
         and rownum <= 10 
        order by total_likes 
        group by p.id) 
order by total_likes 
group by p.id) 

nicht getestet, aber denke, dass so etwas wie dies den Trick tun würde

+1

Union funktioniert, aber es gibt ein kleines Problem: Wenn ein Foto heute und vor einer Woche gemocht wurde, haben die resultierenden Zeilen das gleiche Foto zweimal – pewpewlasers

+1

Bitte finden Sie eine andere Ressource als W3S, weil es schlecht ist und Sie sich schlecht fühlen sollten Sie fördern es. –

+2

http://www.w3fools.com/ – fancyPants

0

Sie die Anzahl der Wochen berechnen kann zwischen heute abgelaufen und das "Like" -Datum und Gruppe von ihnen.

SELECT 
    p.id AS id, COUNT(li.id) AS total_likes, period \ 
FROM `photo` p \ 
    LEFT JOIN `like` li \ 
    ON p.id = li.photo_id \ 
WHERE 
    DATEDIFF(li.date, now())+7)%7 AS period \ 
GROUP BY \ 
    p.id, period 
ORDER by period, total_likes DESC 
LIMI 30