Check in MySQL table if my ID exist in the results - mysql

How to check in MySQL table if my ID exist in the results and return TRUE, but this is a little complicated as I would like to check GROUP of records and not the last one from that GROUP, code below for the table and query which doesn't work, I would like to check if my $session_user_id exist in the GROUP OF auction_bid_item_id but not check last row as the last row is a WINNING ROW.
CREATE TABLE `auction_bids` (
`auction_bid_id` int(11) NOT NULL AUTO_INCREMENT,
`auction_bid_user_id` int(11) NOT NULL,
`auction_bid_seller_id` int(11) NOT NULL,
`auction_bid_item_id` int(11) NOT NULL,
PRIMARY KEY (`auction_bid_id`)
);
MySQL Query:
SELECT * FROM auction_bids
WHERE auction_bid_user_id = '$session_user_id'
GROUP BY auction_bid_item_id;

Join against a subselect which determines if the user is in that group.
Ie, the following will get you the bids and a field saying if the user is found.
SELECT auction_bids.*, IF(Sub1.auction_bid_item_id IS NULL, 'User not found', 'User found')
FROM auction_bids
LEFT OUTER JOIN
(
SELECT DISTINCT auction_bid_item_id
FROM auction_bids
WHERE auction_bid_user_id = '$session_user_id'
) Sub1
ON auction_bids.auction_bid_item_id = Sub1.auction_bid_item_id
GROUP BY auction_bids.auction_bid_item_id
EDIT - try this to try and ignore the latest bid
SELECT auction_bids.*, IF(Sub1.auction_bid_item_id IS NULL, 'User not found', 'User found')
FROM auction_bids
LEFT OUTER JOIN
(
SELECT DISTINCT auction_bids.auction_bid_item_id
FROM auction_bids
LEFT OUTER JOIN
(
SELECT auction_bid_item_id, MAX(auction_bid_id) AS LastBid
FROM auction_bids
GROUP BY auction_bid_item_id
) Sub2
ON auction_bids.auction_bid_item_id = Sub2.auction_bid_item_id
AND auction_bids.auction_bid_id = Sub2.LastBid
WHERE Sub2.auction_bid_item_id IS NULL
AND auction_bid_user_id = '$session_user_id'
) Sub1
ON auction_bids.auction_bid_item_id = Sub1.auction_bid_item_id
GROUP BY auction_bids.auction_bid_item_id

Something like this? (with php)
$id_exists = false;
$id = mysql_real_escape_string($_GET['id']);
$select = "SELECT auction_bid_id FROM auction_bids WHERE auction_bid_id ='$id'";
$result = mysql_query($select);
if(mysql_num_rows($result) > 0){
$id_exists = true;
}else{
$id_exists = false;
}

Related

linq2db update with CTE on MySql 8

This question is about linq2db.MySql 3.1.5 and MySQL 8.0.21
I am getting "You have an error in your SQL syntax..." when trying to run an update (marking duplicate emails) using CTE on MySql as per below
var cte = (
from x in db.GetTable<PEmailCleanupJobItem>()
group x by x.EmailAddress into eGroup
where eGroup.Count() > 1
select new { EmailAddress = eGroup.Key }
).AsCte();
var qry = (
from e in db.GetTable<PEmailCleanupJobItem>()
from d in cte
.InnerJoin(d => e.EmailAddress == d.EmailAddress)
select e
);
await qry
.Set(e => e.IsDuplicate, true)
.UpdateAsync();
This generates and sends the following to MySQL
-- MySql.Official MySql (asynchronously)
DECLARE #IsDuplicate UByte -- Boolean
SET #IsDuplicate = 1
UPDATE `CTE_1` (`EmailAddress`)
AS
(
SELECT
`t1`.`email_address`
FROM
`emails` `t1`
GROUP BY
`t1`.`email_address`
HAVING
Count(*) > 1
)
FROM
`emails` `d`
INNER JOIN `CTE_1` `e` ON (`d`.`email_address` IS NULL AND `e`.`EmailAddress` IS NULL OR `d`.`email_address` = `e`.`EmailAddress`)
SET
`d`.`is_duplicate` = #IsDuplicate
Note how UPDATE `CTE_1` (`EmailAddress`) is generated instead of WITH `CTE_1` (`EmailAddress`)
I would manually write this query (which works) as
WITH `CTE_1` (`EmailAddress`)
AS
(
SELECT
`t1`.`email_address`
FROM
`emails` `t1`
GROUP BY
`t1`.`email_address`
HAVING
Count(*) > 1
)
UPDATE
`emails` `d`
INNER JOIN `CTE_1` `e` ON (`d`.`email_address` IS NULL AND `e`.`EmailAddress` IS NULL OR `d`.`email_address` = `e`.`EmailAddress`)
SET
`d`.`is_duplicate` = 1
Is this a bug with linq2db or am I missing something?

MySQL query on two tables with conditions

I have two tables:
users and users_img.
I need to create one query to select all users from users table that have zip column not empty AND have img column empty in users_images (both tables have user ids: users.id and users_img.user_id so those could be joined).
users
id
name
zip
last_time
users_ids
id
user_id (same as id in users)
img
I tried this:
SELECT * FROM `users` JOIN `users_ids` on users.id = users_ids.user_id
WHERE `zip` != '' AND `img` = '' ORDER BY `last_time` DESC
with no luck. I know is supposed to be quite simple.
it will also work for you
SELECT * FROM `users` as `u`
JOIN `users_ids` as `uid` on `u`.`id` = `uid`.`user_id`
WHERE `u`.`zip` IS NOT NULL
AND `uid`.`img` IS NULL
ORDER BY `u`.`last_time` DESC
I have modified your query to check for Null values also in OR
Try this:
SELECT * FROM `users`
LEFT JOIN `users_ids` on users.id = users_ids.user_id
WHERE (TRIM(`zip`) != '' OR `zip` is not null) AND
(TRIM(`img`) = '' OR `img` is null) ORDER BY `last_time` DESC
This worked:
SELECT * FROM `users` as `u`
LEFT JOIN `users_ids` as `uid` on `u`.`id` = `uid`.`user_id`
WHERE `u`.`zip` != ''
AND `uid`.`img` IS NOT NULL
ORDER BY `u`.`last_time` DESC

SQL Multiple table JOINS, GROUP BY and HAVING

I've a table structured somewhat similar to this:
CREATE TABLE `user`
(`id` int, `name` varchar(7));
CREATE TABLE `email`
(`id` int, `email_address` varchar(50), `verified_flag` tinyint(1),`user_id` int);
CREATE TABLE `social`
(`id` int,`user_id` int);
INSERT INTO `user`
(`id`, `name`)
VALUES
(1,'alex'),
(2,'jon'),
(3,'arya'),
(4,'sansa'),
(5,'hodor')
;
INSERT INTO `email`
(`id`,`email_address`,`verified_flag`,`user_id`)
VALUES
(1,'alex#gmail.com','1',1),
(2,'jon#gmail.com','0',1),
(3,'arya#gmail.com','0',3),
(4,'sansa#gmail.com','1',4),
(5,'reek#gmail.com','0',3),
(6,'hodor#gmail.com','0',5),
(7,'tyrion#gmail.com','0',1)
;
INSERT INTO `social`
(`id`,`user_id`)
VALUES
(1,4),
(2,4),
(3,5),
(4,4),
(5,4)
;
What I want to get is all emails:
which are not verified
which belongs to a user who has no, i.e 0, verified emails
which belongs to a user who has no, i.e 0, social records
With the below query I'm able to apply the 1st and 3rd condition but not the 2nd one:
SELECT *
FROM `email`
INNER JOIN `user` ON `user`.`id` = `email`.`user_id`
LEFT JOIN `social` ON `user`.`id` = `social`.`user_id`
WHERE `email`.`verified_flag` = 0
GROUP BY `email`.`user_id`,`email`.`email_address`
HAVING COUNT(`social`.`id`) = 0
How can I achieve the result?
Here's the sqlfiddle as well
Interesting and tricky one.
I see you've got something going on there. But having and sub queries becomes a VERY bad idea when your tables become large.
See below for an approach. Don't forget to set up your indexes!
SELECT * from email
LEFT JOIN social on email.user_id = social.user_id
-- tricky ... i'm going back to email table to pick verified emails PER user
LEFT JOIN email email2 on email2.user_id = email.user_id AND email2.verified_flag = 1
WHERE
-- you got this one going already :)
email.verified_flag = 0
-- user does not have any social record
AND social.id is null
-- email2 comes in handy here ... we limit resultset to include only users that DOES NOT have a verified email
AND email2.id is null
ORDER BY email.user_id asc;
You can use the following query:
SELECT e.`id`, e.`email_address`, e.`verified_flag`, e.`user_id`
FROM (
SELECT `id`,`email_address`,`verified_flag`,`user_id`
FROM `email`
WHERE `verified_flag` = 0) AS e
INNER JOIN (
SELECT `id`, `name`
FROM `user` AS t1
WHERE NOT EXISTS (SELECT 1
FROM `email` AS t2
WHERE `verified_flag` = 1 AND t1.`id` = t2.`user_id`)
AND
NOT EXISTS (SELECT 1
FROM `social` AS t3
WHERE t1.`id` = t3.`user_id`)
) AS u ON u.`id` = e.`user_id`;
This query uses two derived tables:
e implements the first condition, i.e. returns all emails which are not verified
u implements the 2nd and 3rd condition, i.e. it returns a set of all users that have no verified emails and have no social records.
Performing an INNER JOIN between e and u returns all emails satisfying condition no. 1 which belong to users satisfying conditions no. 2 and 3.
Demo here
You can alternatively use this query:
SELECT *
FROM `email`
WHERE `user_id` IN (
SELECT `email`.`user_id`
FROM `email`
INNER JOIN `user` ON `user`.`id` = `email`.`user_id`
LEFT JOIN `social` ON `user`.`id` = `social`.`user_id`
GROUP BY `email`.`user_id`
HAVING COUNT(`social`.`id`) = 0 AND
COUNT(CASE WHEN `email`.`verified_flag` = 1 THEN 1 END) = 0 )
The subquery is used in order to select all user_id satisfying conditions no. 2 and 3. Condition no. 1 is redundant since if the user has no verified emails, then there is no way a verified email is related to this user.
Demo here
Simply run a Union Query:
SELECT `user_id`, `email_address`, `verified_flag`, 'No Email' as `Type`
FROM `email` RIGHT JOIN `user` ON `user`.`id` = `email`.`user_id`
WHERE `email`.`user_id` IS NULL
UNION
SELECT `user_id`, `email_address`, `verified_flag`, 'Not Verified' as `Type`
FROM `email` INNER JOIN `user` ON `user`.`id` = `email`.`user_id`
WHERE `email`.`verified_flag` = 0
UNION
SELECT `user_id`, `email_address`, `verified_flag`, 'No Social' as `Type`
FROM `email` INNER JOIN `user` ON `user`.`id` = `email`.`user_id`
LEFT JOIN `social` ON `user`.`id` = `social`.`user_id`
GROUP BY `user_id`, `email_address`, `verified_flag`
HAVING COUNT(IFNULL(`social`.`id`, 0)) = 0;
SELECT
u.id AS u_id
, u.name AS u_name
, e.email_address AS e_email
, e.verified_flag AS e_verify
, e.user_id AS e_uid
, s.id AS s_id
, s.user_id AS u_id
, COALESCE(ver_e.ver_email_count,0) as ver_email_count
FROM
email as e
LEFT OUTER JOIN
user as u
ON u.id = e.user_id
LEFT OUTER JOIN
social AS s
ON u.id = s.user_id
LEFT OUTER JOIN
(
SELECT
COUNT(email_address) AS ver_email_count
, user_id
FROM
email
) AS ver_e
ON u.id = ver_e.user_id
GROUP BY
e.user_id
HAVING e.verified_flag = 0
AND
ver_email_count = 0
AND
ISNULL(s.id)
Uses one derived table to get the number of verified email addresses each user has got

Reuse result of IF condtion in true or false result expression

I have the following nested query:
SELECT `messages`.*,
IF((select `status` from messages_status
where messages_status.message_id = messages.id and user_id = 149) IS NULL,
'unread', messages_status.status) as `status`
FROM `messages`
What I would like to do, if there is no messages_status.status set (i.e. if it is NULL), it should return 'unread'. However, if it is set, is should return its value.
Currently, it returns an error: Unknown column 'messages_status.status' in 'field list'
Do you have any idea how to fix this?
You can't refer to the result of the if's condition in other places. You could repeat the query:
IF((select `status` from messages_status
where messages_status.message_id = messages.id and user_id = 149) IS NULL,
'unread',
(select `status` from messages_status
where messages_status.message_id = messages.id and user_id = 149))
as status
But it's probably clearer to use a join instead:
select m.*
, coalesce(ms.status, 'unknown')
from messages m
left join
messages_status ms
on ms.message_id = m.id
and ms.user_id = 149
The coalesce function produces the first of its arguments that is not null.

Getting the last record inserted into a select query

I am creating a small message board and I am stuck
I can select the subject, the original author, the number of replies but what I can't do is get the username, topic or date of the last post.
There are 3 tables, boards, topics and messages.
I want to get the author, date and topic of the last message in the message table. The author and date field are already fields on the messages table but i would need to join the messages and topics table on the topicid field.
this is my query that selects the subject, author, and number of replies
SELECT t.topicname, t.author, count( message ) AS message
FROM topics t
INNER JOIN messages m
ON m.topicid = t.topicid
INNER JOIN boards b
ON b.boardid = t.boardid
WHERE b.boardid = 1
GROUP BY t.topicname
Can anyone please help me get this finished?
This is what my tables look like
CREATE TABLE `boards` (
`boardid` int(2) NOT NULL auto_increment,
`boardname` varchar(255) NOT NULL default '',
PRIMARY KEY (`boardid`)
);
CREATE TABLE `messages` (
`messageid` int(6) NOT NULL auto_increment,
`topicid` int(4) NOT NULL default '0',
`message` text NOT NULL,
`author` varchar(255) NOT NULL default '',
`date` timestamp(14) NOT NULL,
PRIMARY KEY (`messageid`)
);
CREATE TABLE `topics` (
`topicid` int(4) NOT NULL auto_increment,
`boardid` int(2) NOT NULL default '0',
`topicname` varchar(255) NOT NULL default '',
`author` varchar(255) NOT NULL default '',
PRIMARY KEY (`topicid`)
);
if your SQL supports the LIMIT clause,
SELECT m.author, m.date, t.topicname FROM messages m
JOIN topics t ON m.topicid = t.topicid
ORDER BY date desc LIMIT 1
otherwise:
SELECT m.author, m.date, t.topicname FROM messages m
JOIN topics t ON m.topicid = t.topicid
WHERE m.date = (SELECT max(m2.date) from messages m2)
EDIT: if you want to combine this with the original query, it has to be rewritten using subqueries to extract the message count and the date of last message:
SELECT t.topicname, t.author,
(select count(message) from messages m where m.topicid = t.topicid) AS messagecount,
lm.author, lm.date
FROM topics t
INNER JOIN messages lm
ON lm.topicid = t.topicid AND lm.date = (SELECT max(m2.date) from messages m2)
INNER JOIN boards b
ON b.boardid = t.boardid
WHERE b.boardid = 1
GROUP BY t.topicname
also notice that if you don't pick any field from table boards, you don't need the last join:
SELECT t.topicname, t.author,
(select count(message) from messages m where m.topicid = t.topicid) AS messagecount,
lm.author, lm.date
FROM topics t
INNER JOIN messages lm
ON lm.topicid = t.topicid AND lm.date = (SELECT max(m2.date) from messages m2)
WHERE t.boardid = 1
GROUP BY t.topicname
EDIT: if mysql doesn't support subqueries in the field list, you can try this:
SELECT t.topicname, t.author, mc.messagecount, lm.author, lm.date
FROM topics t
JOIN (select m.topicid, count(*) as messagecount from messages m group by m.topicid) as mc
ON mc.topicid = t.topicid
JOIN messages lm
ON lm.topicid = t.topicid AND lm.date = (SELECT max(m2.date) from messages m2)
WHERE t.boardid = 1
GROUP BY t.topicname
If you want to get the latest entry in a table, you should have a DateTime field that shows when the entry was created (or updated). You can then sort on this column and select the latest one.
But if your id field is a number, you could find the highest. But I would recommend against this because it makes many assumptions and you would be fixed to numerical ids in the future.
You can use a subselect. Eg.:
select * from messages where id = (select max(id) from messages)
edit: And if you identify the newest record by a timestamp, you'd use:
select * from messages where id = (
select id
from messages
order by post_time desc
limit 1)
With MySQL this should work:
SELECT author, date, topicname as topic FROM messages LEFT JOIN topics ON messages.topicid = topics.topicid ORDER BY date DESC, LIMIT 0, 1;