2011-11-17 81 views
0

我想按视图/下载对图像列表进行排序。我将统计信息存储在不同的表中,每天保存一行。经过几天的搜索,我设法得到了一个可用的SQL,但由于我几乎做了3次相同的查询,因此效率不高。这里是我的表和SQL:如何从一个子查询中选择多个列而不是多个相似的子查询?

CREATE TABLE "images_stats" (
    "id" integer NOT NULL PRIMARY KEY, 
    "image_id" integer NOT NULL REFERENCES "images_image" ("id"), 
    "date" date NOT NULL, 
    "view_count" integer unsigned NOT NULL, 
    "download_count" integer unsigned NOT NULL 
) 

images_list = Images.objects.raw(''' 
    SELECT *, 
     (SELECT 1.0*SUM(s.view_count)/SUM(s.download_count) 
     FROM images_stats AS s 
     WHERE s.image_id = w.id AND s.date < %s AND s.date >= %s) AS ratio, 
     (SELECT 1.0*SUM(s.view_count)/SUM(s.download_count) 
     FROM images_stats AS s 
     WHERE s.image_id = w.id AND s.date < %s) AS global_ratio, 
     (SELECT COUNT(*)==0 
     FROM images_stats AS s 
     WHERE s.image_id = w.id AND s.date < %s) AS count 
    FROM images_image as w 
    WHERE w.category_id = %s 
    ORDER BY count, ratio, global_ratio 
''', [date.today(), date.today()-timedelta(days=1), date.today(), date.today(), category.id]) 

有谁知道我该如何优化这个SQL?我有一些SQL知识,但显然不够。

回答

0
SELECT *, 
    SUM(case when s.date < %s AND s.date >= %s then s.view_count else 0 end)/ 
    SUM(case when s.date < %s AND s.date >= %s then s.download_count else 0 end) 
     AS ratio, 
    SUM(case when s.date < %s then s.view_count else 0 end)/ 
    SUM(case when s.date < %s then s.download_count else 0 end) 
     AS global_ratio, 
    COUNT(*)==0 AS count 
FROM images_image as w 
LEFT JOIN images_stats AS s 
    ON s.image_id = w.id 
WHERE w.category_id = %s 
GROUP BY w.id 
ORDER BY count, ratio, global_ratio 
+0

看起来很干净,但它不起作用。我得到比例:无以及global_ratio:无。我刚刚意识到我的代码不工作,因为我得到重复的图像,我甚至尝试添加组,但不会帮助。 – andrei