Taking a specific data with MySQL, Group by - php

I want to take most frequently entered datas in last 1 day.
Here is my code:
SELECT tag_id, time,
COUNT(tag_id) AS value_occurrence
FROM tag_rel
GROUP BY tag_id
HAVING time > '$yesterday'
ORDER BY value_occurrence DESC LIMIT 10
Code is working but it has a problem:
I wanna take between july 22 and 23.
id| tag_id | time |
1 | football | 22,5 july |
2 | basketball | 22,5 july |
3 | football | 22,5 july |
4 | football | 21 july |
I want to take first three rows and order them by their frequency.
ex:
1- football
2- basketball
But my code is not taking "football". It just shows "basketball". Because additionally "football" has a time value which is smaller than 22 july.
How can solve it?

The correct query for what you want would use where, not having:
SELECT tag_id, MAX(time) as maxtime,
COUNT(tag_id) AS value_occurrence
FROM tag_rel
WHERE time > '$yesterday'
GROUP BY tag_id
ORDER BY value_occurrence DESC
LIMIT 10;
Otherwise, there is an arbitrary value used for time, both in the select and the having clause.

Related

How to select all entries of a user from a database?

I am trying to make a "top purchaser" module on my store and I am a bit confused about the MySQL query.
I have a table with all transactions and I need to select the person (which could have one or many transactions) with the highest amount of money spent in the past month.
What I have:
name | money spent
------------------
john | 50
mike | 12
john | 10
jane | 504
carl | 99
jane | 12
jane | 1
What I want to see:
With a query, I need to see:
name | money spent last month
-----------------------------
jane | 517
carl | 99
john | 60
mike | 12
How do I do that?
I do not really seem to find many good solutions since my MySQL query skills are quite basic. I thought of making a table in which money is added to the user when he buys something.
That's a simple aggregated query :
SELECT t.name, SUM(t.moneyspent) money_spent_last_month
FROM mytable t
GROUP BY t.name
ORDER BY t.money_spent_last_month DESC
LIMIT 1
The query sums the total money sped by customer name. The results are ordered by descending total money spent, and only the first row is retained.
If you are looking to filter data over last month, you need a column in the table that keeps track of the transaction date, say transaction_date, and then you can just add a WHERE clause to the query, like :
SELECT t.name, SUM(t.moneyspent) money_spent_last_month
FROM mytable t
WHERE
t.transaction_date >=
DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 2 MONTH)), INTERVAL 1 DAY)
AND t.transaction_date <=
DATE_SUB(NOW(), INTERVAL 1 MONTH)
GROUP BY t.name
ORDER BY t.money_spent_last_month DESC
LIMIT 1
This method is usually more efficient than using DATE_FORMAT to format dates as string and compare the results.

php/mysql multiple order by

I am working on a results table at the minute, I am wanting to sort a table, by points (highest at the top), if points are equal I want to sort by goal difference, and then if goal difference is equal I want to sort by goals scored.
So a table may look like this,
+--------+--------+----------+-----------------+--------+
| Team | Scored | Conceded | Goal Difference | Points |
+--------+--------+----------+-----------------+--------+
| Team A | 20 | 10 | +10 | 15 |
| Team B | 20 | 15 | +5 | 15 |
| Team C | 10 | 10 | 0 | 9 |
| Team D | 5 | 5 | 0 | 9 |
+--------+--------+----------+-----------------+--------+
So Team A wins the league because it has a better goal difference than Team B, Team C finish above Team D because they score more goals, and all other things are equal.
Is it possible to order this way in mysql, or will I need to parse the results with PHP?
Guess what, you can pass multiple column names to ORDER BY
SELECT * FROM mytable ORDER BY Points DESC, `Goal Difference` DESC, Scored DESC
You haven't given your table structure, but as pointed out by jpg if these fields are not numeric, ORDER by field_name + 0 may be more appropriate
You can do like this using query
SELECT * from `your_table` ORDER BY points DESC, goal_difference DESC, scored DESC
You can order by multiple columns at the same time.
SELECT some_cols
FROM table
WHERE (some conditions)
ORDER BY col1 DESC, col2, col3;

mysql rank by column value grouped by column value

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

Effectively Firing a multiple query

I was practicing drawing graphs on various statistics for the purpose of data analysis. But I am not able to figure out an efficient way to fire multiple mysql query at the back-end.
I am trying to draw Period Vs No of Visitors graph.
Please Note: Period here refers to week,month,3 months,6 months,1 year,2 years.
Period will be selected by the user from the select box.
For example: When User selects 3 week, I need to construct No of Visitors per 3 week graph.
My DataBase Contains Two Column: For each of the site hit, it records:
(1) timestamp and
(2)user ID.
If I fire query multiple times for each select option, then performance would be quite poor.So, How to do it efficiently?
UPD:
When User Select stats per 3 month:
Then I am firing mysql query as:
Select count(*) From stats_tab WHERE timestamp BETWEEN JAN AND MAR;
Select count(*) From stats_tab WHERE timestamp BETWEEN APR AND JUN;
Select count(*) From stats_tab WHERE timestamp BETWEEN JUL AND SEP;
............
Each count returned from each of the query will be the y-axis value for my graph
When User Select stats per year:
Then I am firing mysql query as:
Select count(*) From stats_tab WHERE timestamp BETWEEN 2009 AND 2010;
Select count(*) From stats_tab WHERE timestamp BETWEEN 2010 AND 2011;
Select count(*) From stats_tab WHERE timestamp BETWEEN 2011 AND 2012;
............
Don't hit database with multiple queries. Get all your values with one query appropriately applying GROUP BY and WHERE
SELECT YEAR(timestamp) year, COUNT(*) total
FROM stats_tab
WHERE timestamp BETWEEN NOW() - INTERVAL 3 YEAR AND NOW()
GROUP BY YEAR(timestamp);
SELECT MONTH(timestamp) month, COUNT(*) total
FROM stats_tab
WHERE timestamp BETWEEN NOW() - INTERVAL 6 MONTH AND NOW()
GROUP BY MONTH(timestamp);
SELECT DAY(timestamp) day, COUNT(*) total
FROM stats_tab
WHERE timestamp BETWEEN NOW() - INTERVAL 7 DAY AND NOW()
GROUP BY DAY(timestamp);
Sample output:
| YEAR | TOTAL |
----------------
| 2011 | 2 |
| 2012 | 1 |
| 2013 | 9 |
| MONTH | TOTAL |
-----------------
| 2 | 1 |
| 3 | 2 |
| 5 | 1 |
| DAY | TOTAL |
---------------
| 20 | 1 |
| 21 | 1 |
| 22 | 1 |
Here is SQLFiddle demo

Display data based on timeframe with SUM

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

Categories