There's a little thing I'm stuck with. I've a table in my database like:
id | AuthorId | Book
---------------------
1 | 2 | book name
2 | 2 | book name
3 | 2 | book name
4 | 2 | book name
5 | 5 | book name
6 | 5 | book name
7 | 8 | book name
8 | 9 | book name
9 | 9 | book name
10 | 6 | book name
As you can see, Author ID "2" is repeated the highest times in this table ( 4 times ) while the author Author IDs appeared less then 4 times. How can I get the ID "2" from this table using php MySQLi, which is the most frequently occurring value in this data? I've no idea how can I do this.
Thank you very much.
Try the following query. You count rows grouped by AuthorID DESC , and limiting the result to the top value.
SELECT AuthorId, COUNT(AuthorId) as c from table
GROUP BY AuthorId
ORDER BY COUNT(AuthorId) DESC
LIMIT 1;
Try this
select AuthorId , count(AuthorId ) as max
from table_name
group by AuthorId order by max desc limit 1;
The order by max desc is for ordering the max value at the first row. The limit 1 is from getting only the first row
Related
I am joining users table with selected_course table and course table with selected_course, my requirement is I want to get those users with course_id=2 and in same row select using concatenation of all courses which is selected by user.
user table
id name
1 user_1
2 user_2
user_education_details
id user_id education_id selected_course
1 1 1 2
2 2 1 2
3 1 2 4
4 3 1 2
5 3 2 4
Actual Requirement:
user_id required_course user_all_courses course_name
1 2 2,4 a,b
2 2 2 a
3 2 2,4 a,b
Using codeigniter query format:
$this->db->select('users.*');
$this->db->from('users');
$this->db->join('selected_course sc','c.user_id=users.id');
$this->db->join('course c','c.id=sc.selected_course');
$this->db->where('sc.selected_course',$course_id=2);
$this->db->get()->result();
A HAVING clause is what you're looking for. To filter data based on a group use this clause.
SELECT
ued.user_id,
2 AS required_course, -- passed course id
GROUP_CONCAT(ued.selected_course) AS user_all_courses,
GROUP_CONCAT(c.name) course_name
FROM user_education_details ued
INNER JOIN courses c ON ued.selected_course = c.id
GROUP BY user_id
HAVING SUM(IF(selected_course = 2, 1,0)) > 0;
Output:
| user_id | required_course | user_all_courses | course_name |
| 1 | 2 | 4,2 | b,a |
| 2 | 2 | 2 | a |
| 3 | 2 | 2,4 | a,b |
You can also order user_all_courses and course_name by using a ORDER BY clause inside GROUP_CONCAT. Here is one example.
GROUP_CONCAT(ued.selected_course ORDER BY selected_course ASC) AS user_all_courses,
Now you can quickly convert this to your equivalent CodeIgniter query.
Check this working fiddle for the same.
I am trying to order a db table by champion name but using id from another table and if that ID = Champion ID then it will order.
I tried this but it does not order properly it seems to miss place some rows in the order so i think my query is missing something. I have tried with asc and desc and still comes out buggy
SELECT Plat_PLUS_Champion_Stats.*
FROM Plat_PLUS_Champion_Stats, Champion_Data
WHERE concat(Plat_PLUS_Champion_Stats.Champ_ID, '.jpg') =
Champion_Data.Champion_Sub_Background
ORDER BY Champion_Data.Champion
The aim would be to get data from this table
Champion_Data Table
id Champion Champion_Sub_Background
---|------------|-------------------------|
6 | Janna | 80.jpg |
5 | Karthus | 123.jpg |
7 | Aatrox | 45.jpg |
1 | Talon | 95.jpg |
Plat_PLUS_Champion_Stats Table
id Champ_ID
---|------------|
6 | 80 |
5 | 45 |
7 | 123 |
1 | 95 |
The aim is to get the Champ_ID and compare to Champion_Sub_Background if both the same number then to show the Champion ordered desc.
I shortened the table names for clarity. Using your select, it's difficult to see if the order is correct:
select stats.*
from champion_data as data, plat_plus_champion_stats as stats
where concat(stats.champ_id, '.jpg')=data.champion_sub_background
order by data.champion desc
id champ_id
1 95
7 123
6 80
5 45
So I added in the table with the names:
select stats.*, data.*
from champion_data as data, plat_plus_champion_stats as stats
where concat(stats.champ_id, '.jpg')=data.champion_sub_background
order by data.champion desc
id champ_id id champion champion_sub_background
1 95 1 Talon 95.jpg
7 123 5 Karthus 123.jpg
6 80 6 Janna 80.jpg
5 45 7 Aatrox 45.jpg
Your query is working fine; it just needs DESC in the ORDER BY. Most likely you got confused with the id field. It doesn't match up between the two tables-- notice the difference between id fields for Karthus and Aatrox. It'd be easy to get confused using them to judge if the order is correct.
I have a table with many columns. Each row contains a unique ID field. How can I select 5 rows without selecting a row with id stored in variable $doNot.
Currently I am using the following query.
$qry="SELECT title, link FROM posts WHERE id > (SELECT MAX(id) - 5 FROM news)";
Consider this table:
id | title | link
_____________________________________
1 | title_1 | link_1
2 | title_2 | link_2
3 | title_3 | link_3
4 | title_4 | link_4
5 | title_5 | link_5
6 | title_6 | link_6
7 | title_7 | link_7
8 | title_8 | link_8
I want to select 5 rows except row with id '3' using the above query from the above table
SELECT title, link FROM posts WHERE NOT (id = $doNot) LIMIT 5
Use LIMIT to specify the number of rows to be returned:
SELECT title, link
FROM posts
ORDER BY ID DESC
LIMIT 5
If $doNot is a table variable, you should be able to simply sub-query on posts.id:
SELECT title, link FROM posts WHERE id NOT IN (SELECT id FROM $doNot) LIMIT 5;
I have a huge number of rows that I'd like to get say, last 5 records inserted in that database from 10 different users. If the same user inserted the last 3 rows into database, we must get one row, skip the others two and move to get a row per user, until it count up to 5.
A database like that:
user_id | news_id | title
1 | 1 | foo-1
2 | 2 | foo-2
3 | 3 | foo-3
1 | 4 | baa
4 | 5 | baa0
5 | 6 | baa1
5 | 7 | baa2
6 | 8 | baa3
7 | 9 | baa4
Should return:
user_id | news_id | title
1 | 1 | foo-1
2 | 2 | foo-2
3 | 3 | foo-3
4 | 5 | baa0
5 | 6 | baa1
The current filter was done by PHP, like this:
$used = array();
while ($data = mysql_fetch_array($query)) {
$uid = $data['user_id'];
if(in_array($uid, $used))
continue;
array_push($used, $uid);
// do something with data
}
But I want to refactor it, and do the filter purely by mysql, if possible. I don't know much MySql and that's why I'm having problem to archive this...
Here's what I've tried
select DISTINCT(user_id), news_id, title from XXX
WHERE GROUP BY (news_id) DESC
LIMIT 0,5
How can I do that?
1 way you can do it is to generate a partitioned row number per user and then select 5 records where RowNumber = 1.
SELECT *
FROM
(
SELECT
d.user_id
,d.news_id
,d.title
,(#rn:= if(#uid = user_id, #rn + 1,
if(#uid:=user_id,1,1)
)
) as RowNumber
FROM
Data d
CROSS JOIN (SELECT #uid:=-1, #rn:=0) vars
ORDER BY
user_id
,news_id
) t
WHERE
t.RowNumber = 1
ORDER BY news_id
LIMIT 5;
http://rextester.com/JRIZI7402 - example to show it working
Note you can change the row order by simply changing the ORDER BY statement of the derived table so if you have a column that will signify the latest record e.g. an identity column or a datetime column you can use that, but user_id must be the first criteria to be partitioned correctly.
Do it from your query.
"SELECT * FROM table GROUP BY user_id ORDER BY news_id DESC LIMIT 5"
well, i think this will achieve what you are after.
select user_id, news_id, title from tableName
GROUP BY user_id
ORDER BY news_id DESC
LIMIT 0,5
Hope this helps!
In a blog-like website, all the users can "star" a news (= bookmark it, mark it as "favourite").
I have a mysql table for stats.
table_news_stats
id_news
total_stars (int) //Total number of users who starred this news
placement (int)
The placement field is intuitive: if you order all the news by the total_stars field you get each news placement. So, the news with most stars will be number 1, and so on.
So, suppose I have 700 records in my table_news_stats, and for each one I have the id and the total_stars count, how can I update the placement field automatically for each record? Which query is faster/better?
Example of the table_news_stats content:
First record (A):
1-3654-?
Second record (B):
2-2456-?
Third record (C):
3-8654-?
If you order the record by stars count:
the sequence of records is C - A - B
So... the result will be:
First record (A):
1-3654-2
Second record (B):
2-2456-3
Third record (C):
3-8654-1
Clarification:
why would I ever need the placement field at all?
It's pretty simple... the placement field will be populated by a cronjob the first day of every month. Basically it will provide a 'snapshot' of the rank of each news in terms of popularity (as it was at the beginning of the current month). As a consequence, thanks to the placement field, I will have the following information:
"The 1st day of this month the 'top starred' news list was like this:
1- News C
2- NewsA
3- News B "
Then, with a query "SELECT * FROM table_news_stats ORDER BY total_stars DESC" I can obtain the new ranking (in real-time).
As a consequence, I will have the following information:
"At the time the page is loaded, the 'top starred' news list is like this:
1- News A
2- News C
3- News B "
Finally, by comparing the two rankings, I obtain the last piece of information:
"News A has gained a position" +1
"News C has lost a position" -1
"News B has no change in position" +0
If there is a better way of doing this, let me know.
I guess you don't need to update the table just:
SELECT *
FROM table_news_stats
ORDER BY total_stars DESC
But if you want to know the place of each one you can:
SELECT *, IF(#idx IS NULL,#idx:= 1,#idx:= #idx+1)
FROM table_news_stats
ORDER BY total_stars DESC
And if you still need to update something like:
UPDATE table_news_stats
SET placement = FIND_IN_SET(id_news,(SELECT GROUP_CONCAT(t.id_news) FROM (SELECT id_news
FROM table_news_stats
ORDER BY total_stars DESC) t ))
SQLFiddle
Consider the following
mysql> select * from test ;
+------+-------------+-----------+
| id | total_stars | placement |
+------+-------------+-----------+
| 1 | 3 | 0 |
| 2 | 6 | 0 |
| 3 | 7 | 0 |
| 4 | 2 | 0 |
| 5 | 9 | 0 |
| 6 | 2 | 0 |
| 7 | 1 | 0 |
+------+-------------+-----------+
Now using the following you can update the placement as
update test t1 join
(
select *,
#rn:= if(#prev = total_stars,#rn,#rn+1) as rank ,
#prev:= total_stars
from test,(select #rn:=0,#prev:=0)r
order by total_stars desc
)t2
on t2.id = t1.id
set t1.placement = t2.rank ;
mysql> select * from test order by placement ;
+------+-------------+-----------+
| id | total_stars | placement |
+------+-------------+-----------+
| 5 | 9 | 1 |
| 3 | 7 | 2 |
| 2 | 6 | 3 |
| 1 | 3 | 4 |
| 4 | 2 | 5 |
| 6 | 2 | 5 |
| 7 | 1 | 6 |
+------+-------------+-----------+
Note that in case of tie will have the same placement.