2013-07-19 37 views
3

問題:查找每個類別中至少有10個項目的前2個用戶。每組,找到頭數爲N的用戶,使用SUM(x)> = N

表結構:

CREATE TABLE items(
    id INT AUTO_INCREMENT PRIMARY KEY, 
    datetime datetime, 
    category INT, 
    user INT, 
    items_count INT 
); 

 

樣本數據:

INSERT INTO items (datetime, category, user, items_count) VALUES 
('2013-01-01 00:00:00', 1, 1, 10), 
('2013-01-01 00:00:01', 1, 2, 1), 
('2013-01-01 00:00:02', 1, 3, 10), 
('2013-01-01 00:00:03', 1, 2, 9), 

('2013-01-01 00:00:00', 2, 4, 10), 
('2013-01-01 00:00:01', 2, 1, 10), 
('2013-01-01 00:00:01', 2, 5, 10); 

 

期望的結果:

category user 
1   1 
1   3 
2   4 
2   5 

 

注:由於該結果所示,我需要能夠顯示對用戶偏好當多個用戶同時滿足要求。

 

SQL小提琴:

http://sqlfiddle.com/#!2/58e60

 

這是我曾嘗試:

SELECT 
    Derived.*, 
    IF (@category != Derived.category, @rank := 1, @rank := @rank + 1) AS rank, 
    @category := category 


FROM(
    SELECT 
    category, 
    user, 
    SUM(items_count) AS items_count, 
    MAX(datetime) AS datetime 


    FROM items 


    GROUP BY 
    category, 
    user 

    HAVING 
    SUM(items_count) >= 10 
) AS Derived 


JOIN(SELECT @rank := 0, @category := 0) AS r 


HAVING 
    rank <= 2 

ORDER BY 
    Derived.category, 
    Derived.datetime 

 

但它是錯誤的。它不僅不採取用戶優先考慮,它會產生錯誤的結果與像這樣的數據:

('2013-01-01 00:00:00', 1, 1, 10), 
('2013-01-01 00:00:01', 1, 2, 1), 
('2013-01-01 00:00:02', 1, 3, 10), 
('2013-01-01 00:00:03', 1, 2, 9), 
('2013-01-01 00:00:10', 1, 3, 1); 

 

其他信息:我不知道,如果程序可在這一個差異情況,但不幸的是它也不是一種選擇。運行此查詢的用戶只具有SELECT權限。

+0

該帖子的演示文稿似乎只是尖叫作業;和你很像[tag:mysql],我想知道是否應用功課。就這樣。 –

+0

爲什麼user_id 2不可見,它似乎在類別1中有10個項目 – Akash

+0

@BradChristie:[家庭作業標記已被棄用。](http://meta.stackexchange.com/q/147100/161666) –

回答

0

我嘗試了戈登的查詢,但不幸的是它似乎不適用於大型表格;等待15分鐘後,我決定殺死它。 但是下面的查詢對我來說效果很好,它在大約8秒內咀嚼了大約6M行的表格。

#Variable 
SET @min_items  = 10, 
    @max_users  = 2, 
    @preferred_user = 5, 

    #Static 
    @category  = 0, 
    @user   = 0, 
    @items   = 0, 
    @row_num  = 1; 


-- 


SELECT 
    category, 
    user, 
    datetime 


FROM(
    SELECT 
    category, 
    user, 
    datetime, 
    IF (@category = category, @row_num := @row_num + 1, @row_num := 1) AS row_num, 
    @category := category 


    FROM(
    SELECT 
     category, 
     user, 
     datetime, 
     IF (@user != user, @items := 0, NULL), 
     IF (@items < @min_items, @items := @items + items_count, NULL) AS items_cumulative, 
     @user := user 


    FROM items 


    ORDER BY 
     category, 
     user, 
     datetime 
) AS Derived 


    WHERE items_cumulative >= @min_items 


    ORDER BY 
    category, 
    datetime, 
    FIELD(user, @preferred_user, user) 
) AS Derived 


WHERE row_num <= @max_users; 
2

爲了找到滿足您需求的用戶,您需要累計計數總和。以下查詢查找用戶首次達到10個單位的時機。如果計數是從來沒有否定,那麼就只有一個:

select i.* 
from (select i.*, 
      (select sum(items_count) 
       from items i2 
       where i2.user = i.user and 
        i2.category = i.category and 
        i2.datetime <= i.datetime 
      ) as cumsum 
     from items i 
    ) i 
where cumsum - items_count < 10 and cumsum >= 10 
order by datetime; 

爲了得到前兩個,你需要使用MySQL的技巧組內計數。下面是一般工作的例子:

select i.* 
from (select i.*, if(@prevc = category, @rn := @rn + 1, @rn := 1) as rn, @prevc := category 
     from (select i.*, 
        (select sum(items_count) 
        from items i2 
        where i2.user = i.user and 
          i2.category = i.category and 
          i2.datetime <= i.datetime 
        ) as cumsum 
      from items i 
      ) i 
      cross join 
      (select @rn := 0) const 
     where cumsum - items_count < 10 and cumsum >= 10 
    ) i 
where rn <= 2 
order by category, datetime; 

我有這種方法的一個問題,因爲沒有在MySQL中說,表達@prevc := category實際上計算爲rn後計算。但是,似乎是這樣,這似乎在實踐中起作用。

相關問題