With PHP and MySQL I am trying to display items with most votes over a certain period of time (24 hour, 1 week, 1 year, etc). When someone votes on an item, a table records the user, item id, vote, and time, like so:
Table1
username | itemid | vote | time
asdf | 127 | 1 | 1306726126
asdf | 124 | -1 | 1306726123
bob | 127 | 1 | 1306726129
bob | 124 | 1 | 1306726123
Now, I have another table with item details.
Table2
itemid | name | category | date | etc
What I WANT to do is call a table to display all the data from table 2 for only items with votes in the last 24hours and sort it by the votes. This means I need to SUM votes with TIME < 24 hours, then RIGHT JOIN (?) to my other database? I don't know, I am having difficulty figuring out how I should go about doing this. Any suggestiongs?
Something like this should work.
SELECT SUM(Table1.vote) as votes, Table2.* FROM Table2
LEFT JOIN Table1 ON Table1.itemid=Table2.itemid
WHERE Table1.`time`>=DATE_SUB(Table1.`time`, INTERVAL 24 HOUR)
GROUP BY Table1.itemid
ORDER BY Table1.votes DESC
Related
I have mysql table as follows:
|id | subject | link | week_number
------------------------------------
| 1 | ABC | link1 | week-1
| 2 | DEF | link2 | week-2
| 3 | GHI | link3 | week-3
------------------------------------
Now I want To show week-1 record to user for one week after login and from his registration date as initial date for week counting....
then in next week, week-1 and week-2 should be visible,
then in next week, week-1, week-2 and week-3 records should be visible.
I am completely blank...so didn't tried any code....
your help or guideline appreciated...
If you have a registration date, just make your live easier and change the column week_number to days_after_reg - and the values to 7,14,21
Then you just need to compare this number with the current offset:
SELECT * from linktable WHERE `days_after_reg` <= datediff(Now(), UserRegistrationDate)
Either insert the user date with a variable, or "join" the tables.
Note that the join has no join condition here, so don't forget to filter on user-id (or name or something).
SELECT l.subject, l.link from linktable l cross join
users u WHERE `l.days_after_reg` <= datediff(Now(), u.registrationDate)
and u.id=5
Hello I think I try here something complicated. Maybe you can help me out here.
I have two tables: earnings and payouts.
Earnings has userid, amount, timestamp as datetime and other stuff. It has just information when user was earning something.
Example:
id | user_id | amount | timestamp |
1 | 2 | 1050 | 31days ago |
2 | 1 | 20 | 10days ago |
3 | 1 | 10 | 9 days ago |
4 | 2 | 10000 | 9 days ago |
...
Payouts has userid, amount, timestamp as datetime and has entries about payouts if a user is above x earnings lets say 1000. Example
id | user_id | payout_amount | timestamp |
1 | 2 | 1050 | 30days ago |
...
To my problem now. I want to COUNT how many payouts are NOT done (who has no entry in payout). This means. I need to compare payouts.timestamp with earnings.timestamp which has same userid and check if there are newer entries then the payouts. If yes then count it how many (so I think here its needed to sum first the earnings). I am not even sure if this is possible.
I can do it also with php if this isn't possible alone with mysql.
For example the result should be: count = 2 because userid 1 has just 30 earnings so he didn't reach the 1000 also he has no entry in payouts table. Userid 2 has 10000 but he still has no payouts because we didn't execute it or make a entry in the payouts table. he just has a old payout and the new earnings isn't paid.
Edit: the 10days ago things are just example. I use there real datetime types
EDIT2: Forget to say I tried this one:
select COUNT(e.amount) FROM earnings e, payouts p where p.payout_timestamp < e.timestamp AND p.user_id = e.user_id GROUP BY p.user_id, e.user_id
and go this:
| Count(e.amount) |
| 2 |
| 1 |
I think that comparing timestamps is not the only way to get result that you need. If these to tables correctly represent history of earnings and payments then you may just sum up total earnings and payments for each user and compare them counting every user_id that has less payments than earnings.
For example:
SELECT user_id, SUM(amount) as amount FROM earnings GROUP BY user_id;
sums up earnings for each user,
SELECT user_id, SUM(payout_amount) as amount FROM payouts GROUP BY user_id;
sums up payments for each user.
Now left join them and count users who has less payments than earnings:
SELECT COUNT(e1.user_id) FROM (SELECT user_id, SUM(amount) as amount FROM earnings GROUP BY user_id) as e1 LEFT JOIN (SELECT user_id, SUM(payout_amount) as amount FROM payouts GROUP BY user_id) as p1 ON e1.amount > p1.amount;
For your tables example my result was:
+-------------------+
| COUNT(e1.user_id) |
+-------------------+
| 2 |
+-------------------+
And to find users with payments not done just use the same query without COUNT() function:
+---------+
| user_id |
+---------+
| 2 |
| 1 |
+---------+
In my opinion this way is more stable because it is possible to have recent payments with less amount than total user earnings at the moment of payment, e.g.:
1) user earned 1000
2) then user earned 2000
3) and after that user been payed 1000
In this situation comparing timestamps without comparing amounts of payments will show you that this user has no payments to be done whereas you still need to pay him 2000.
I am trying to figure out how to rank based on 2 different column numbers in laravel but raw mysql will do. I have a list of videos, these videos are inside of competitions and are given votes if someone likes the video. Each video will have a vote number and a competition number. I am trying to rank based on votes within competition. So for example below I have competition 8, I need the rank of all the videos in that competition based on votes. I then need the same for competition 5 etc.
|rank|votes|competition|
------------------
| 1 | 100 | 8 |
------------------
| 2 | 50 | 8 |
------------------
| 3 | 30 | 5 |
------------------
| 1 | 900 | 5 |
------------------
| 2 | 35 | 5 |
------------------
I have tried various group and selectby methods but nothing seems to work, any ideas?
In Mysql you can use user-defined variables to calculate rank,case statement checks if competition is same as the previous row then increment rank by one if different then assign 1 an order by is needed to have correct rank for the video
SELECT t.*,
#current_rank:= CASE WHEN #current_rank = competition
THEN #video_rank:=#video_rank +1
ELSE #video_rank:=1 END video_rank,
#current_rank:=competition
FROM t ,
(SELECT #video_rank:=0,#current_rank:=0) r
ORDER BY competition desc, votes desc
See Demo
If you are confused with the last extra column you can use a subselect
See Demo
You can use windowing functions:
select
competition, votes, rank() over (partition by competition order by votes desc) as rank
from
table1
Database data:
id | account | date | random_data
1 | 1 | 01/01/2013 | qw
2 | 2 | 05/01/2013 | er
3 | 2 | 09/01/2013 | ty
4 | 1 | 05/01/2013 | ui
5 | 2 | 11/01/2013 | op
6 | 1 | 12/01/2013 | as
Hi, so let's say I want the records starting from 05/01/2013 - note that prev_date for the 1st row still shows an earlier date than 05/01 meaning that the whole table still needs to be searched.
Result data:
account | cur_date | random_data | prev_date | prev_rand_data
1 | 05/01/2013 | ui | 01/01/2013 | qw
1 | 12/01/2013 | as | 05/01/2013 | ui
2 | 05/01/2013 | er | null | null
2 | 09/01/2013 | ty | 05/01/2013 | er
2 | 11/01/2013 | op | 09/01/2013 | ty
So I'm not sure what is the best, most optimized query I could use for this. I'm not opposed to a php solution but not sure how much better that would be. Some ideas I've considered:
Some sort of join on the same table - not sure how though
Sub queries on the select -
select date as cur_date
, (select max(date)
from table
where date < cur_date
group by account)
as prev_date... - this seems like it could be incredibly intensive
Session variables - set a session variable on each row which will be the previous data for the next row e.g.
select date as cur_date
, #prev_date as prev_date
, #prev_date:=date...
Has anyone had any experience with a problem like this and was there a good solution? Are there any positives negatives with any of the ideas I have that could cause problems in the future?
I would use a combination of sql and application code. Since I am not a php programmer, I will only describe the logic to use for the application part.
First the query.
select account, date, random_data
from thetable
where date >= YourDateVariable
union
select account, date, random_data
from thetable join
(select account acc, max(date) maxdate
from thetable
where date <= YourDateVariable
group by account) x on account = acc and date = max(date)
where date <= YourDateVariable
order by account, date
For the application code, do this:
Set a variable called ThisAccount to 0.
Set a row counter variable to 0.
Create an empty 2D array
Start looping through your query results
Put the account value and random data into the first two columns
of the next available row of the array
Compare the account value to the value of the ThisAccount variable.
If they are the same, get the previous date and random data from
the previous row in the array.
Set the ThisAccount variable to the current account value.
Increment your row counter variable
End of loop.
I have 2 tables.
Table 1 = branch
containing
branch_id
branch_name
Table 2 = sales_data
containing
sales_id
sales_date
sales_branch
sales_profit
I need away of showing the total daily sales and total daily profit for each branch. I know how to bring back the result for a given week etc I am just really struggling on how to pull back the data.
I also need all the branches to be shown at all time and if they haven't sold anything to display a 0.
I have put together a quick image (http://i37.photobucket.com/albums/e71/dannyflap/screen_shot.jpg) of how I would like the finished. This is really driving me nuts :(
UPDATE
select sales_branch, WEEKDAY(sales_date), COUNT(sales_profit), SUM(sales_profit)
FROM sales_date
GROUP BY sales_branch, WEEKDAY(sales_date)
This then brings back the following example. Figures are made up.
sales_branch, day, units, profit:
| branch1 | 0 (as day) | 16 | 439 |
| branch1 | 1 (as day) | 12 | 651 |
| branch1 | 2 (as day) | 22 | 312 |
| branch1 | 3 (as day) | 61 | 614 |
| branch1 | 4 (as day) | 12 | 541 |
| branch1 | 5 (as day) | 24 | 102 |
| branch1 | 6 (as day) | 21 | 145 |
I guess you would have to do an outer join on table 1's branch_id and table 2's sales_branch and loop through the result to produce the table. With an outer join those branches who haven't sold anything will get a NULL, I think.
Is it the table generating you're having problem with? I don't think it's wise to do some spectacular SQL for this problem. My two cents.
You're going to need a foreign key in sales_data that maps to branch.
assuming sales_branch is something different than branch_name or branch_id, sales_data should contain:
sales_id sales_date sales_branch branch_id sales_profit
Also - you should post your code for getting back the result for a given week and we can help you build on that rather than give you the entire answer.
EDIT
Ok with modifying your sales_data table to have a foreign key branch_id to the branch table, this query should get you closer to what you're looking for.
SELECT b.branch_name, WEEKDAY(s.sales_date), COUNT(s.sales_profit), SUM(s.sales_profit)
FROM branch b
LEFT OUTER JOIN sales_data on s.branch_id = b.branch_id
GROUP BY b.branch_id, WEEKDAY(s.sales_date)