2011-03-22 73 views
3

好的,我在这里有一个有趣的问题。我有两张桌子,小费和选票。提示如下:按两个字段的总数排序

tip_id, challenge_id, user_id, ip_address, tip_date, tip_text 

投票看起来是这样的:

tip_id, ip_address, vote_date, vote 

用户可以在一个挑战张贴提示,然后其他用户就可以在前端用拇指向上或向下投票。投票中的投票字段是布尔型,0代表拇指向下,1代表拇指向上。挑战可以有许多提示。

我一直在拍我的大脑,而我却无法让它工作。我需要一个查询,可以获得特定提示的上下投票数,这两个数字的差异(所以如果有2个投票和1个投票,差异将是1)作为评分,还有来自提示表的提示数据,然后将其与最高评分先排序。假设我们有两个提示,a和b:

一:3时,2倒(DIFF:1) B:4时,1倒(DIFF:3)

在这种情况下,B将到来首先是因为它比a的评分更高,上下选票的数量差距更大。

举个例子,假设我有一个ID为1的提示,其中有4个投票和2个反对票,这意味着相差2,并且这个提示与挑战ID5相关,我的回归可能看起来像这个:

up | down | rating | tip_id | tip_date | user_id | tip_text 
------------------------------------------------------------ 
3 | 2 | 1  | 1  | 12345678 | 1  | "this is a tip" 

现在我已经能够做到了,但是如果遇到多个提示的时候遇到问题,就会出现多行问题。比方说,挑战ID 5有2个技巧,那么我应该得到的结果是这样的:

up | down | rating | tip_id | tip_date | user_id | tip_text 
------------------------------------------------------------ 
3 | 2 | 1  | 1  | 12345678 | 1  | "this is a tip" 
4 | 1 | 3  | 1  | 87654321 | 2  | "this is also a tip" 

随着每个尖端得到它自己的行中的结果。现在发生的事情是,我得到了一个上下的值,这个值是挑战的总票数,而不是小费。因此,使用上面的第二个例子,而不是两个单独的行,我会得到一行的值为7,下降为3,这个挑战的所有提示的总数上下。

我确定这将涉及到加入和排序和分组,但我不在乎这个查询有多复杂,我只是不想在PHP中做到这一点。最终,我想为查询提供一个质询ID,并让它获得X行,其中X是针对该质询ID的提示数量,并且每行将包含该提示ID的计数。

任何帮助将不胜感激,因为我用完头发拔出。不幸的是,这是我的项目的界定点,评分较高的提示需要在列表中显得更高。

编辑:这是我目前正在工作的查询。我一个良好的夜间睡眠后对其作出了一些调整,并得到了它主要的工作,但还是有,我不能解释一个问题:

SELECT 
    COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END) AS up, 
    COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END) AS down, 
    (COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END)) AS rating, 
    T.* 
    FROM votes V, tips T 
    WHERE T.challenge_id = 10 
    GROUP BY V.tip_id 
    ORDER BY rating DESC 

这得到我需要的一切,所有的提示和选票一个具体的挑战,每个提示的新行(而不是总计,就像我之前得到的)。问题是,我的上下票和评分都是它的两倍。因此,如果我有一个提示有3票和1票的提示,并且评分为2,则此查询将显示我有6票和2票的评分为4。我想我可以简单地用PHP将这个数字除以2,但这并不能解决问题,它只是一个绷带。任何人都可以看到为什么我得到两倍的数字,我应该得到?我会不断地搞乱它,也许试试一下左连接,希望我能弄明白,但是能有更多的双眼更好。

+0

当然你不会有2行你有相同的'tip_id'。由于每个提示的'tip_id'会有所不同?或者我在这里错过了简单的东西?什么是你用于第一个表的MySQL语句,你可以得到什么? – anothershrubery 2011-03-22 12:18:28

+0

你能否包含你的(部分)工作的查询? – Ishtar 2011-03-22 12:20:48

+0

我现在在工作,当我回家时,我会发布半工作查询。至于tip_id,在提示表中,不,每行都会有它自己的tip_id。但是,在投票表中,我使用tip_id作为父项来将投票与提示相关联,因此在投票表中可以有任意数量的具有相同tip_id的行。 – HaLo2FrEeEk 2011-03-23 01:11:48

回答

-1

好吧,我最终改变该ianhales provided查询,并得到了我想要的东西。随着他的更新wuery,我得到了正确的数字,但由于INNER JOIN,我没有得到没有投票的提示。我的变化是简单的,但他们完美地工作:

SELECT 
    COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END) AS up, 
    COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END) AS down, 
    (COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END)) AS rating, 
    T.* 
    FROM tips T 
    LEFT JOIN votes V 
    ON T.tip_id = V.tip_id 
    WHERE T.challenge_id = 10 
    GROUP BY T.tip_id 
    ORDER BY rating DESC 

这得到所有的提示,即使他们没有投票权,并通过评级降序对它们进行分类,从而可以获得更额定提示首先出现在列表。

你一直很棒,你可以期待你的名字出现在我的项目中。非常感谢。

2

怎么是这样的:

SELECT v.up, v.down, (v.up - v.down) AS rating, t.tip_id, t.tip_date, t.user_id, t.tip_text 
FROM tips AS t 
INNER JOIN votes AS v 
ON t.tip_id = v.tip_id 
WHERE challenge_id=1 
ORDER BY rating DESC; 

然后你就可以将它传递到MySQL之前设置在PHP中WHERE条款的challenge_id值。我认为这应该会给你以后的东西,尽管因为我已经使用了INNER JOIN,所以你需要确保“提示”中的每一行在“投票”中都有一行,否则它将被忽略。

编辑:

基于新的信息

(对不起,我以前不正确读取的问题,希望我这样做是正确这一次!):

SELECT 
    COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END) AS up, 
    COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END) AS down, 
    (COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END)) AS rating, 
    T.* 
    FROM votes V 
    INNER JOIN tips AS T 
    ON T.tip_id = V.tip_id 
    WHERE T.challenge_id = 1 
    GROUP BY V.tip_id 
    ORDER BY rating DESC; 

我刚在SQLite3中测试了这个(在简化的表格上),它似乎工作正常。我使用的数据是:

sqlite> select * from votes 
    ...> ; 
tip_id  vote  
---------- ---------- 
2   1   
2   1   
2   1   
2   0   
2   0   
3   0   
3   0   
3   0   
3   1   
4   0   
4   0   
4   1   
4   1   
4   1   
4   1  

其中给出结果:

up   down  rating  tip_id  challenge_id user_id 
---------- ---------- ---------- ---------- ------------ ---------- 
4   2   2   4   1    4   
3   2   1   2   1    2   
1   3   -2   3   1    3   
+0

在投票表中实际上没有名为“up”或“down”的列,只有一个布尔值,其中0表示反对票,1表示反对票。当我提出半工作查询时,它会更有意义。 – HaLo2FrEeEk 2011-03-23 01:14:23

+0

根据您的更新编辑我的答案:) – n00dle 2011-03-23 15:01:38

+0

我试了一下,它确实得到了正确的计数,但有一个问题,它只获得有投票的提示。对于没有投票的提示,不会返回任何内容。有没有办法解决这个问题?我尝试了T.tip_id的分组,并做了一个左外连接,没有骰子。如果我使用提示加入投票表,而不是其他方式...... – HaLo2FrEeEk 2011-03-23 23:02:09