mysql select table from anther table from $_GET - mysql

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";

Related

Get index of certain result in query results list?

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

MySQL returning all matches from a table and indicating if an id is on another table

How can I return, on a select, a field that indicates that an id was found?
My goal is to return all songs(song) from a specific source(source) checking if an user(user) has it or not (user_song).
The query I made almost works. If I remove 'hasSong' (which Im trying to indicate that an user has a song or not), I can see all songs.
If I keep 'hasSong', I see all songs repeating the song for each user.
QUERY:
SELECT DISTINCT(song.id) AS id_song, CONCAT(song.article, ' ', song.name) AS name
FROM `song`
LEFT JOIN `user_song` ON `song`.`id` = `user_song`.`id_song`
LEFT JOIN `user` ON `user`.`id` = `user_song`.`id_user`
JOIN `song_source` ON `song`.`id` = `song_source`.`id_song`
WHERE `song_source`.`id_source` = '1'
AND ( `user_song`.`id_user` = '3' OR song.id = song_source.id_song )
ORDER BY `song`.`name` ASC
DB:
CREATE TABLE `song` (
`id` int(11) NOT NULL,
`article` varchar(10) NOT NULL,
`name` varchar(150) NOT NULL,
`shortname` varchar(150) NOT NULL,
`year` int(11) NOT NULL,
`artist` int(11) NOT NULL,
`duration` int(11) NOT NULL,
`genre` int(11) NOT NULL,
`updated` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `song_source` (
`id_song` int(11) NOT NULL,
`id_source` int(11) NOT NULL
)
CREATE TABLE `source` (
`id` int(11) NOT NULL,
`article` varchar(10) NOT NULL,
`name` varchar(150) NOT NULL,
`updated` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`email` varchar(100) NOT NULL,
`password` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user_song` (
`id_user` int(11) NOT NULL,
`id_song` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The specification isn't entirely clear, ...
To return all songs (with no repeated values of song.id) that are from a particular source (id_source='1'),
along with an indicator, a value of 0 or 1, that tells us if there's a row in user_song that matches on id_song and is related to a particular user,(id_user = '3')
something like this:
SELECT s.id AS id_song
, MAX( CONCAT(s.article,' ',s.name) ) AS name
, MAX( IF(us.id_user = '3' ,1,0) ) AS has_song
FROM `song` s
JOIN `song_source` ss
ON ss.id_song = s.id
AND ss.id_source = '1'
LEFT
JOIN `user_song` us
ON us.id_song = s.id
AND us.id_user = '3'
GROUP BY s.id
ORDER BY MAX(s.name)
There are a couple of other query patterns that will return an equivalent result. For example, we could use a correlated subquery in the SELECT list.
SELECT s.id AS id_song
, MAX( CONCAT(s.article,' ',s.name) ) AS name
, ( SELECT IF( COUNT(us.id_user) >0,1,0)
FROM `user_song` us
WHERE us.id_song = s.id
AND us.id_user = '3'
) AS has_song
FROM `song` s
JOIN `song_source` ss
ON ss.id_song = s.id
AND ss.id_source = '1'
GROUP BY s.id
ORDER BY MAX(s.name)
These queries are complicated by the fact that there are no guarantees of uniqueness in any of the tables. If we had guarantees, we could eliminate the need for a GROUP BY and aggregate functions.
Please consider adding PRIMARY and/or UNIQUE KEY constraints on the tables, to prevent duplication. The way the tables are defined, we could add multiple rows to song with the same id value. (And those could have different name values.)
(And the queries would be much simpler if we had some guarantees of uniqueness.)

How can I query for rows with latest date and do an inner join on a second table?

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

how can i get all post for me and for user who i follow him

i have 3 table.
1st is for user info.
2nd is for post where user insert to it and relation with user table by user_id.
3rd is for user who i follow him and relation with user table by user_id.
now in home page i need to show all posts where i insert on it and where user i follow him insert into table post.
i will try to make this MySQL by :-
SELECT * FROM users ,
(SELECT * FROM events where ev_user_id in
(
( select * from follow where follow.fo_user_id = '".$user_id."' )
, '".$user_id."'
)
) as post
where post.ev_user_id = users.id
order by post.ev_date DESC limit $to , $from
where $user_id is id for user.
here i get error that:-
Operand should contain 1 column(s)
if i follow one user its work, but when i follow more than one user, its display above error.
how can i get all post for me and for user who i follow him
====================================
events table is the table for post
CREATE TABLE `events` (
`ev_id` int(11) NOT NULL auto_increment,
`ev_user_id` int(11) NOT NULL,
`ev_type` varchar(222) NOT NULL,
`ev_text` text NOT NULL,
`ev_pic` varchar(222) NOT NULL,
`ev_date` varchar(22) NOT NULL,
PRIMARY KEY (`ev_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=211 ;
table for user which i follow him
CREATE TABLE `follow` (
`fo_id` int(11) NOT NULL auto_increment,
`fo_user_id` int(11) NOT NULL,
`fo_user_id_follow` int(11) NOT NULL,
`fo_date` varchar(22) NOT NULL,
PRIMARY KEY (`fo_id`),
UNIQUE KEY `fo_user_id` (`fo_user_id`,`fo_user_id_follow`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=15 ;
table for user info
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`fullname` varchar(222) NOT NULL,
`username` varchar(60) NOT NULL,
`password` varchar(64) NOT NULL,
`email` varchar(50) NOT NULL,
`address` varchar(300) NOT NULL,
`phone` varchar(20) NOT NULL,
`skype` varchar(20) NOT NULL,
`facebook` varchar(40) NOT NULL,
`msn` varchar(90) NOT NULL,
`mobile` varchar(20) NOT NULL,
`more` text NOT NULL,
`time` varchar(50) NOT NULL,
`lastlogin` varchar(50) NOT NULL,
`role_id` tinyint(1) NOT NULL default '2',
`code` varchar(7) NOT NULL,
`active` tinyint(4) NOT NULL default '3',
`wieght` int(11) NOT NULL,
`tall` int(11) NOT NULL,
`birthdate` varchar(20) NOT NULL,
`gender` varchar(5) NOT NULL,
`fat` int(11) NOT NULL,
`fittnes` int(11) NOT NULL,
`status` int(11) NOT NULL,
`pic` varchar(222) NOT NULL,
`regdate` varchar(22) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=396 ;
This should get you the posts and user info of the users your $user_id follows ordered by descending date.
SELECT * FROM events
JOIN follow ON events.ev_user_id = follow.fo_user_id
JOIN users ON events.ev_user_id = user.id
WHERE follow.fo_user_id_follow = '".$user_id."'
ORDER BY events.ev_date DESC
LIMIT $to , $from
Is this what you wanted? not completelly sure.
EDIT: to add also your own posts as well as the ones form the users you follow.
SELECT * FROM events
JOIN follow ON events.ev_user_id = follow.fo_user_id
JOIN users ON events.ev_user_id = user.id
WHERE follow.fo_user_id_follow = '".$user_id."'
OR events.ev_user_id = '".$user_id."'
ORDER BY events.ev_date DESC
LIMIT $to , $from
EDIT: the enquirer's exact solution, Daren had understood the follow relationship reversed.
SELECT * FROM events
JOIN follow ON events.ev_user_id = follow.fo_user_id_follow
JOIN users ON events.ev_user_id = users.id
WHERE follow.fo_user_id = '".$user_id."'
OR events.ev_user_id = '".$user_id."'
ORDER BY events.ev_date DESC
LIMIT $to , $from"
The error message you're getting, is because you're using the IN operator against a subquery that returns more than one column. Maybe rewrite your SQL to something like this:
SELECT * FROM users ,
(SELECT * FROM events where ev_user_id in
(
( select user_id from follow where follow.fo_user_id = '".$user_id."' )
, '".$user_id."'
)
) as post
where post.ev_user_id = users.id
order by post.ev_date DESC limit $to , $from
I guess - You should provide specific column instead of * at the line -
( select * from follow where follow.fo_user_id = '".$user_id."' )
you could try with the below line -
select fo_user_id_follow from follow where follow.fo_user_id = '".$user_id."'
what about the following?
SELECT * FROM users
INNER JOIN follow ON fo_user_id=users.id
INNER JOIN events ON ev_user_id IN (users.id,fo_user_id_follow)
WHERE users.id='$user_id' ORDER BY post.ev_date DESC LIMIT $to , $from
You will probably get too many columns as it will list all the columns from all joined tables.
Edit: added ' around user_idjust in case users.id is a varchar column ...
Edit: widened criterion for user_id: ev_user_id IN (users.id,fo_user_id_follow)
rewrite:
SELECT * FROM follow
INNER JOIN users ON users.id=ev_user_id IN (users.id,fo_user_id_follow)
INNER JOIN events ON ev_user_id=users.id
WHERE users.id='$user_id' ORDER BY post.ev_date DESC LIMIT $to , $from
This should give you information about all users (including yourself) and all posts from these users that follow the user identified by $user_id. Probably not a good choice either, since you will have the full user information given again and again for each post.
It would be better to have two queries and two result tables: 1. user info, 2. posts of these users.
SELECT * FROM user
WHERE users.id IN (
SELECT fo_user_id_follow FROM follow WHERE fo_user_id=$user_id )
OR users.id=$user_id
and
SELECT * FROM events
WHERE ev_user_id IN (
SELECT fo_user_id_follow FROM follow WHERE fo_user_id=$user_id )
OR ev_user_id=$user_id

Doing a COUNT in MySQL

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;