I have the following two tables -- userprofile and videoinfo. videoInfo has a FK to userprofile.
CREATE TABLE `userprofile_userprofile` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`full_name` varchar(100) NOT NULL,
...
)
CREATE TABLE `userprofile_videoinfo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(256) NOT NULL,
`uploaded_by_id` int(11) NOT NULL,
...
KEY `userprofile_videoinfo_e43a31e7` (`uploaded_by_id`),
CONSTRAINT `uploaded_by_id_refs_id_492ba9396be0968c` FOREIGN KEY (`uploaded_by_id`) REFERENCES `userprofile_userprofile` (`id`)
)
What is the SQL statement I would use to show the count of videos each userprofile has and order by COUNT?
SELECT u.id as userId, count(v.uploaded_by_id) as videosCount
FROM userprofile_userprofile u
LEFT OUTER JOIN userprofile_videoinfo v
ON v.uploaded_by_id = u.id
GROUP BY u.id
ORDER BY count(v.uploaded_by_id) DESC
SELECT uploaded_by_id, COUNT(ID) as cnt
FROM userprofile_videoinfo
GROUP BY uploaded_by_id
ORDER BY cnt DESC;
Related
I've been trying to even write this title in a way that makes most sense, but through much googling I have not found anything to match what I am looking.
Basically, I have a database that stores players and their different levels, and I already have a working query that fetches a list of all players and ranks them in the required order (Total prestige first, then level, then experience and lastly by the oldest update timestamp)
The query I use for this is:
SELECT u.id, u.username, u.mode, u.total_prestige as prestige, u.total_level as level, u.total_xp as exp, s.created FROM hs_users u JOIN hs_userskill s ON u.id = s.userId
WHERE s.id IN (SELECT MAX(id) FROM hs_userskill WHERE userId = u.id GROUP BY userId)
ORDER BY total_prestige DESC, total_level DESC, total_xp DESC, created ASC;
But now, on a different page, I need to find the players "rank" (so basically their index in the results list)
Is there a proper sql way of doing this (probably), instead of just taking the whole results set into code and looping over it? As I am tempted at doing at this point in time.
My database structure in sql:
CREATE TABLE IF NOT EXISTS `hs_modes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`modename` varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`modeicon` varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `hs_skills` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`skillname` varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`skillicon` varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `hs_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL UNIQUE,
`mode` int(11) NOT NULL DEFAULT '0',
`total_prestige` int(11) NOT NULL DEFAULT '0',
`total_level` int(11) NOT NULL DEFAULT '0',
`total_xp` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
FOREIGN KEY (`mode`) REFERENCES `hs_modes`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `hs_userskill` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userId` int(11) NOT NULL,
`skillId` int(11) NOT NULL,
`prestige` int(11) NOT NULL,
`experience` int(11) NOT NULL,
`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
FOREIGN KEY (`userId`) REFERENCES `hs_users`(`id`),
FOREIGN KEY (`skillId`) REFERENCES `hs_skills`(`id`),
UNIQUE KEY `userskill` (`userId`, `skillId`, `prestige`, `experience`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
In mysql 8 you have ROW_NUMBER to signify the position in the specified order
SELECT
u.id,
u.username,
u.mode,
u.total_prestige AS prestige,
u.total_level AS level,
u.total_xp AS exp,
s.created
,ROW_NUMBER() OVER(ORDER BY total_prestige DESC , total_level DESC , total_xp DESC , created ASC) rn
FROM
hs_users u
JOIN
hs_userskill s ON u.id = s.userId
WHERE
s.id IN (SELECT
MAX(id)
FROM
hs_userskill
WHERE
userId = u.id
GROUP BY userId)
ORDER BY total_prestige DESC , total_level DESC , total_xp DESC , created ASC;
Fro Bob rank
SELECT
*
FROM
(SELECT
u.id,
u.username,
u.mode,
u.total_prestige AS prestige,
u.total_level AS level,
u.total_xp AS exp,
s.created
,ROW_NUMBER() OVER(ORDER BY total_prestige DESC , total_level DESC , total_xp DESC , created ASC) rn
FROM
hs_users u
JOIN
hs_userskill s ON u.id = s.userId
WHERE
s.id IN (SELECT
MAX(id)
FROM
hs_userskill
WHERE
userId = u.id
GROUP BY userId)
) t1
WHERE username = 'Bob'
Set the database connection cursor to fetch the result as dictionary, then you can access the data as dictionary index of it's column names
forum_question :
CREATE TABLE IF NOT EXISTS `forum_question` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`question` text NOT NULL,
`subject_id` int(11) NOT NULL,
`student_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `subject_id` (`subject_id`,`student_id`),
KEY `student_id` (`student_id`)
)
forum_answer table
CREATE TABLE IF NOT EXISTS `forum_answer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`answer` text NOT NULL,
`question_id` int(11) NOT NULL,
`faculty_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `question_id` (`question_id`,`faculty_id`),
KEY `faculty_id` (`faculty_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
and subject table
CREATE TABLE IF NOT EXISTS `subject` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(150) NOT NULL
)
Try this edited query, I am sure this will work
SELECT
COUNT(que.id) AS totalQuestions,
(SELECT COUNT(DISTINCT(forum_answer.id))
FROM
forum_answer
WHERE
forum_answer.question_id = que.id
GROUP BY que.id)
AS totalAns
FROM
forum_question que
INNER JOIN
subject sub
ON (que.subject_id = sub.id)
WHERE
que.id > 0
GROUP BY sub.id
If by total you mean the total amount of rows, you can do the following:
`SELECT COUNT(*) FROM forum_question WHERE subject_id=YOURSUBJECT`
if you want just all rows, remove the WHERE clause.
Please you can try this Query
SELECT
subject.name AS subject_name,
count(forum_question.id) AS total_question,
(SELECT count(forum_answer.id)
FROM
forum_answer
WHERE
forum_answer.question_id = forum_question.id) AS total_answer
FROM
subject
Inner Join forum_question ON subject.id = forum_question.subject_id
GROUP BY subject.id
Sorry it was my mistake. now I edited the query and hope it will work for you
all.
I have 2 mysql tables type myisam
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `users_ratings` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`created_date` varchar(255) DEFAULT NULL,
`user_id` mediumint(9) DEFAULT NULL,
`rating1` mediumint(9) DEFAULT NULL,
`rating2` mediumint(9) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Dump can be downloaded here
I want all users to select and sort the list by rating2 and rating2 must be > 1000
SELECT * FROM users as u
INNER JOIN (SELECT rating2, user_id,MAX(created_date) as maxdate FROM `users_ratings` GROUP BY user_id) as x ON x.user_id = u.id
INNER JOIN users_ratings as ur ON(ur.created_date = x.maxdate and ur.user_id = u.id)
WHERE x.rating2 > 1000
ORDER by ur.rating2
Without such an index the query is executed for 9 seconds.
All possible codes, which I thought was allowed to reduce the time of the request to 1-2 seconds.
Help the right to place indexes
I suspect you want the following query. Assuming you do, and performance is still an issue, provide the EXPLAIN for same...
(this assumes a Unique Key on user_id,[rating2,]created_date, which hasn't actually been specified)
SELECT u.*
, x.*
FROM users u
JOIN users_ratings x
ON x.user_id = u.id
JOIN
( SELECT user_id
, MAX(created_date) maxdate
FROM users_ratings
WHERE rating2 > 1000
GROUP
BY user_id
) y
ON y.user_id = x.user_id
AND y.maxdate = x.created_date
ORDER
BY x.rating2;
All the examples I've seen show how to do an inner join using an alias to get rows with the latest date. I can do that with my data but I also want to do an inner join on another table and can't figure how to do both with the same query.
Here are the two tables:
CREATE TABLE `titles` (
`titleID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`titlename` tinytext NOT NULL,
`url` varchar(255) DEFAULT '',
`category` int(2) unsigned NOT NULL,
`postdate` date NOT NULL,
PRIMARY KEY (`titleID`),
KEY `category` (`category`),
CONSTRAINT `titles_ibfk_1` FOREIGN KEY (`category`) REFERENCES `categories` (`catid`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
CREATE TABLE `stats` (
`statid` int(11) unsigned NOT NULL AUTO_INCREMENT,
`score` decimal(3,2) DEFAULT NULL,
`views` int(11) unsigned DEFAULT NULL,
`favs` int(11) DEFAULT NULL,
`comments` int(11) DEFAULT NULL,
`updatedate` date NOT NULL,
`title` int(11) unsigned NOT NULL,
PRIMARY KEY (`statid`),
KEY `title` (`title`),
CONSTRAINT `stats_ibfk_1` FOREIGN KEY (`title`) REFERENCES `titles` (`titleID`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;
My goals:
1) I want a query that gives me all the latest stats for each title.
2) I want to see the text name of the title (from the titles table).
I can use this query to get the latest score for each title.
select t.score, t.views, t.favs, t.comments, t.updatedate, t.title
from stats t
inner join (
select title, max(updatedate) as updatedate
from stats
GROUP BY title
) tm on t.title = tm.title and t.updatedate = tm.updatedate
But the problem with this query is that it displays the title column from stats which is an int. I want the text name of the title.
I can do this to get the title name and the score, but then I'm not getting the row with the latest date.
select titlename, score, updatedate
from stats
inner join titles
on titleid = title
How can I write a query that achieves both my goals?
You need to join the title table in this case as
select
s1.score,
s1.views,
s1.favs,
s1.comments,
s1.updatedate,
t.titlename
from titles t
join stats s1 on s1.title = t.titleID
join (
select title, max(updatedate) as updatedate
from stats
GROUP BY title
) s2 on s2.title = s1.title and s1.updatedate = s2.updatedate
I need to select id from sub where mainid = $cccc as iiid and after that select from ads where cat = iiid
and select order from ads order by id desc limit 10
$cccc=intval($_GET['cat']);
$DB = new DB;
$seleddcddddtMainwork ="select id from sub where mainid='$cccc' as iiid from ads where cat='$idididid' order by id desc limit 10 ";
I tried many codes with that but it's not work with me.
I tried:
select sub.mainid='$cccc' as idididid from ads where cat='$idididid' order by id desc limit 10
but I need to get id from sub where mainid=cccc and ahter that select from ads where cat = that id
CREATE TABLE IF NOT EXISTS `ads` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`userid` int(255) NOT NULL,
`title` varchar(255) NOT NULL,
`photo` varchar(255) NOT NULL,
`message` varchar(255) NOT NULL,
`price` int(255) NOT NULL,
`contery` varchar(255) NOT NULL,
`mobile` varchar(255) NOT NULL,
`showmobile` int(255) NOT NULL,
`showj` int(255) NOT NULL DEFAULT '0',
`youtuube` varchar(255) NOT NULL,
`cat` int(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `photo` (`photo`),
KEY `title` (`title`),
KEY `message` (`message`),
KEY `price` (`price`),
KEY `contery` (`contery`),
KEY `mobile` (`mobile`),
KEY `showmobile` (`showmobile`),
KEY `show` (`showj`),
KEY `youtuube` (`youtuube`),
KEY `userid` (`userid`),
KEY `cat` (`cat`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
CREATE TABLE IF NOT EXISTS `sub` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`mainid` int(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`),
KEY `mainid` (`mainid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=126 ;
My last try was:
select id from sub.mainid='$cccc' as idididid from ads where cat='idididid' order by id desc limit 10
did not work either.
All I have one value $cccc=intval($_GET['cat']); that I need to select id from sub where mainid=$cccc as iit and select from ads where cat=iit
Another thing
SELECT sub.id, sub.mainid
FROM sub
WHERE sub.mainid = '2'
and
result of this sub.id result from ads where cat = sub.id
Why dont you do a join? If you want to select the id from table #1 in table #2, then you should join the two tables by the id value:
$cccc=intval($_GET['cat']);
$DB = new DB;
$seleddcddddtMainwork ="select S.id from sub S JOIN ads A ON S.mainid=A.id AND C.cat='$idididid' AND S.mainid='$cccc' order by S.id desc limit 10";
Make sure you select all the columns you need. In the query above, only the column id from the sub table is being selected:
select S.id from ....
To select the columns id, name and mainid from sub and the field message and price from ads:
$cccc=intval($_GET['cat']);
$DB = new DB;
$seleddcddddtMainwork ="select S.id, S.name, S.mainid, A.message, A.price from sub S JOIN ads A ON S.id=A.mainidAND C.cat='$idididid' AND S.mainid='$cccc' order by S.id desc limit 10";
Edit:
I changed the JOIN ON 'S.id=A.id' to 'S.id=A.mainid' I believe those are the ids you want to join.
In response to your comment:
all i have one value $cccc=intval($_GET['cat']); that i need to select
id from sub where mainid=$cccc as iit and select from ads where
cat=iit
You can do the following:
$cccc=intval($_GET['cat']);
$DB = new DB;
$seleddcddddtMainwork ="select S.id, S.name, S.mainid as iit, A.message, A.price from sub S JOIN ads A ON S.mainid=A.cat AND S.mainid='$cccc' order by A.id desc limit 10";