How to simplify embedded mysql query into a JOIN? - mysql

I recently read something about performance problems with embedded mysql queries, so I wanted to know how I could change the following to a "JOIN" (supposedly with better performance?).
I have two tables:
CREATE TABLE IF NOT EXISTS `blog_categories` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`category_name` varchar(300) COLLATE utf8_unicode_ci NOT NULL,
`category_name_url` varchar(300) COLLATE utf8_unicode_ci NOT NULL,
`category_status` enum('online','offline') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'offline'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=8 ;
CREATE TABLE IF NOT EXISTS `blog_articles` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`article_title` tinytext COLLATE utf8_unicode_ci NOT NULL,
`category_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=26 ;
The logic is basically to select all the categories that have articles associated with them. Each row in the blog_articles table includes a category_name
And here is the query I'm using (which checks out and works fine):
$sql = "SELECT category_name
, category_name_url
FROM blog_categories
WHERE (
(SELECT COUNT(*)
FROM blog_articles, blog_categories
WHERE blog_articles.category_name = blog_categories.category_name
) > 0
AND blog_categories.category_status = 'online')";
I'm still new to "JOIN", and am not sure how to change it when using "COUNT(*)" in the mix too.

Rather than COUNT(*) > 0, use EXISTS
"SELECT category_name, category_name_url FROM blog_categories WHERE EXISTS (" .
"(SELECT 1 FROM blog_articles INNER JOIN blog_categories
ON blog_articles.category_name = blog_categories.category_name) AND " .
"blog_categories.category_status = 'online'" .
")";
This is the old style join syntax:
SELECT 1 FROM blog_articles, blog_categories
WHERE blog_articles.category_name = blog_categories.category_name
This is the ANSI form of the same:
SELECT 1
FROM blog_articles
INNER JOIN blog_categories
ON blog_articles.category_name = blog_categories.category_name
Update (in response to posters comments): This query does what you require:
"SELECT category_name, category_name_url
FROM blog_categories
WHERE category_name IN (SELECT DISTINCT category_name FROM blog_articles)
AND blog_categories.category_status = 'online'"

I'd use EXISTS:
$sql = "SELECT category_name
, category_name_url
FROM blog_categories
WHERE EXISTS
( SELECT *
FROM blog_articles
WHERE blog_articles.category_name = blog_categories.category_name
)
AND blog_categories.category_status = 'online'
";
or JOIN:
$sql = "SELECT c.category_name
, c.category_name_url
FROM blog_categories AS c
JOIN blog_articles AS a
ON a.category_name = c.category_name
WHERE c.category_status = 'online'
GROUP BY c.category_name
";
#Jay: I doubt your query as it is, shows only categories that have articles posted. It counts all articles from all categories and then either shows all categories (if the count is > 0) or no categories at all (if the count = 0).
The reason is that the blog_categories in your subquery is not related to the blog_categories in the main query by any condition.

You can try this also:
SELECT category_name, category_name_url
FROM blog_categories
WHERE category_id IN (
SELECT blog_categories.category_id
FROM blog_articles
INNER JOIN blog_categories
ON blog_categories.category_name = blog_articles.category_name
AND blog_categories.category_status = 'online'
)

Related

Unknown column due to second-level subquery nesting

I want to retrieve a user's rank based on how many points the given user has compared to other users (simply counting users with more points than the given user).
However, with all the queries I have tried, I always end up with Column not found: users.id. From what I can read there is a limit from referencing correlated parent columns more than one level up.
Can I refactor my query, or do I really need to use SET #rownum := 0 style of queries?
SELECT
`users`.*,
(
SELECT COUNT(*) + 1
FROM (
SELECT SUM(`amount`) AS `all_points`
FROM `points`
WHERE `type` = ?
GROUP BY `user_id`
HAVING `all_points` > (
SELECT SUM(`amount`)
FROM `points`
WHERE `type` = ? and `user_id` = `users`.`id`
)
) `points_sub`
) as `rank`
FROM `users`
WHERE `users`.`id` = ?
LIMIT 1
You can move your sub clause one level up, Remove having filter and use where filter
SELECT
`users`.*,
(
SELECT COUNT(*) + 1
FROM (
SELECT user_id,SUM(`amount`) AS `all_points`
FROM `points`
WHERE `type` = ?
GROUP BY `user_id`
) `points_sub`
WHERE `all_points` >
SELECT SUM(`amount`)
FROM `points`
WHERE `type` = ? and `user_id` = `users`.`id`
) as `rank`
FROM `users`
WHERE `users`.`id` = ?
LIMIT 1
I think the below query should work for you. You can pass the user_id of user whose rank you want to compute in both the arguments.
SELECT
`users`.*,
(
SELECT COUNT(*) + 1
FROM (
SELECT SUM(`amount`) AS `all_points`
FROM `points`
WHERE `type` = ?
GROUP BY `user_id`
HAVING `all_points` > (
SELECT COALESCE(SUM(`amount`),0)
FROM `points`
WHERE `type` = ? and `user_id` = ?
)
) `points_sub`
) as `rank`
FROM `users`
WHERE `users`.`id` = ?
LIMIT 1

GROUP_CONCAT in subquery returns one row only

I have some troubles to finish my Mysql Query to return me what I need to have. I am new to such long queries in MYSQL.
SELECT
lang_rel_a_id,
lang_rel_b_id,
lang_rel_id,
tla.text_lang_t AS atext,
lald.lang_data_lang_id AS laid,
lald.lang_data_position AS lapp,
lald.lang_data_font_weight AS lafw,
lald.lang_data_font_size AS lafs,
lald.lang_data_font_color AS lafc,
lald.lang_data_bg_color AS labg,
lasdf.funca AS lafunc,
lang_ship,
lbld.lang_data_lang_id AS lbid,
lbld.lang_data_position AS lbpp,
lbld.lang_data_font_weight AS lbfw,
lbld.lang_data_font_size AS lbfs,
lbld.lang_data_font_color AS lbfc,
lbld.lang_data_bg_color AS lbbg,
tlb.text_lang_t AS btext,
lbsdf.funcb AS lbfunc
FROM lang_relation
LEFT JOIN
(SELECT *, GROUP_CONCAT(text_func_t SEPARATOR ', ') AS funca
FROM synt_data_func
LEFT JOIN text_func ON text_func_id = synt_df_func
GROUP BY synt_df_lang_data
)
lasdf ON lang_rel_a_id = lasdf.synt_df_lang_data
LEFT JOIN lang_data lald ON lald.lang_data_id = lang_rel_a_id
LEFT JOIN text_lang tla ON lald.lang_data_lang_id = tla.text_lang_id
LEFT JOIN
(SELECT *, GROUP_CONCAT(text_func_t SEPARATOR ', ') AS funcb
FROM synt_data_func
LEFT JOIN text_func ON text_func_id = synt_df_func
GROUP BY synt_df_lang_data
)
lbsdf ON lang_rel_b_id = lbsdf.synt_df_lang_data
LEFT JOIN lang_data lbld ON lbld.lang_data_id = lang_rel_b_id
LEFT JOIN text_lang tlb ON lbld.lang_data_lang_id = tlb.text_lang_id
WHERE lang_rel_a_id < lang_rel_b_id
GROUP BY lang_rel_id
I have a relation of two languages in my lang_relation table. I need to query for each of them 2 subtables but the one of them is a relation table that contains the relation between the lang_data_id (= lang_rel_a_id OR lang_rel_b_id, = synt_df_lang_data) and text of the different language functions where multiple values are possible.
I do not understand why the group_concat in this subquery returns only one row. If I do only this query, I get all the results. But when I put it into this larger query, everything's fine but this.. is ..not.
My language_relation table
CREATE TABLE `lang_relation`
(
`lang_rel_id` int(11) NOT NULL,
`lang_rel_a_id` int(11) NOT NULL,
`lang_rel_b_id` int(11) NOT NULL,
`lang_ship` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The joined lang_data
CREATE TABLE `lang_data` (
`lang_data_id` int(11) NOT NULL,
`lang_data_pic_key` int(11) NOT NULL,
`lang_data_position` tinyint(1) NOT NULL,
`lang_data_lang_id` int(11) NOT NULL,
`lang_data_font_weight` tinyint(2) NOT NULL,
`lang_data_font_size` tinyint(2) NOT NULL,
`lang_data_font_color` tinyint(2) NOT NULL,
`lang_data_bg_color` tinyint(2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And the synt_data_func. The text_table is a simple 2-column-table with id + text.
CREATE TABLE `synt_data_func` (
`synt_df_id` int(11) NOT NULL,
`synt_df_lang_data` int(11) NOT NULL,
`synt_df_func` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
I tried different approachs. This seems to be the one that is the nearest of what I need. I don't know how many times I changed the GROUP BY clauses, I even tried to do the CONCAT_GROUP in the parent SELECT..
I even wonder if this is possible because the subqueries are going for 2 different IDs .. is this the problem?
Thanks for any hint in advance.
I finally got it. Maybe it will help somebody with a similar question. I changed my approach for this query.
SELECT
lrel.lang_rel_pic_key,
lrel.lang_rel_id,
langdata_a.lascore,
lasdf.func_a,
langdata_a.latext,
lasf.score_astyle,
SUM(lasf.score_astyle) + (langdata_a.lascore) AS atotal,
lang_ship,
langdata_b.lbtext,
langdata_b.lbscore,
lbsdf.func_b,
lbsf.bformat,
lbsf.score_bstyle,
SUM(lbsf.score_bstyle) + (langdata_b.lbscore) AS btotal
FROM lang_relation lrel
INNER JOIN
(
SELECT DISTINCT
lald.lang_data_id,
lafw.field_value AS lafweight,
lafs.field_value AS lafsize,
lafc.field_value AS laffc,
lafbg.field_value AS lafbg,
lapos.field_value AS laposa,
tla.text_lang_t AS latext,
SUM(lafw.field_value) + (lafs.field_value) + (lafc.field_value) + (lafbg.field_value) + (lapos.field_value) AS lascore
FROM lang_data lald
LEFT JOIN text_lang tla ON lald.lang_data_lang_id = tla.text_lang_id
LEFT JOIN `fields` lafw ON lald.lang_data_font_weight = lafw.field_id
LEFT JOIN `fields` lafs ON lald.lang_data_font_size = lafs.field_id
LEFT JOIN `fields` lafc ON lald.lang_data_font_color = lafc.field_id
LEFT JOIN `fields` lafbg ON lald.lang_data_bg_color = lafbg.field_id
LEFT JOIN `fields` lapos ON lald.lang_data_position = lapos.field_id
GROUP BY lald.lang_data_id
)
langdata_a ON langdata_a.lang_data_id = lrel.lang_rel_a_id
LEFT JOIN
(SELECT sdf.synt_df_lang_data, GROUP_CONCAT(latf.text_func_t) AS func_a
FROM synt_data_func sdf
INNER JOIN text_func latf ON latf.text_func_id = sdf.synt_df_func
GROUP BY sdf.synt_df_lang_data
)
lasdf ON lasdf.synt_df_lang_data = lrel.lang_rel_a_id
LEFT JOIN
(
SELECT sfb.synt_format_lang_data,
sfb.synt_format_fields_id,
GROUP_CONCAT(sfbf.field_text SEPARATOR ', ') AS aformat,
SUM(sfbf.field_value) AS score_astyle
FROM synt_format sfb
INNER JOIN `fields` sfbf ON sfbf.field_id = sfb.synt_format_fields_id
GROUP BY sfb.synt_format_lang_data
)
lasf ON lasf.synt_format_lang_data = lrel.lang_rel_a_id
INNER JOIN
(
SELECT DISTINCT
lbld.lang_data_id,
lbfw.field_value AS lbfweight,
lbfs.field_value AS lbfsize,
lbfc.field_value AS lbffc,
lbfbg.field_value AS lbfbg,
lbpos.field_value AS lbposa,
tlb.text_lang_t AS lbtext,
SUM(lbfw.field_value) + (lbfs.field_value) + (lbfc.field_value) + (lbfbg.field_value) + (lbpos.field_value) AS lbscore
FROM lang_data lbld
LEFT JOIN text_lang tlb ON lbld.lang_data_lang_id = tlb.text_lang_id
LEFT JOIN `fields` lbfw ON lbld.lang_data_font_weight = lbfw.field_id
LEFT JOIN `fields` lbfs ON lbld.lang_data_font_size = lbfs.field_id
LEFT JOIN `fields` lbfc ON lbld.lang_data_font_color = lbfc.field_id
LEFT JOIN `fields` lbfbg ON lbld.lang_data_bg_color = lbfbg.field_id
LEFT JOIN `fields` lbpos ON lbld.lang_data_position = lbpos.field_id
GROUP BY lbld.lang_data_id
)
langdata_b ON langdata_b.lang_data_id = lrel.lang_rel_b_id
LEFT JOIN
(SELECT sdfb.synt_df_lang_data, GROUP_CONCAT(lbtf.text_func_t) AS func_b
FROM synt_data_func sdfb
INNER JOIN text_func lbtf ON lbtf.text_func_id = sdfb.synt_df_func
GROUP BY sdfb.synt_df_lang_data
)
lbsdf ON lbsdf.synt_df_lang_data = lrel.lang_rel_b_id
LEFT JOIN
(
SELECT sfb.synt_format_lang_data,
sfb.synt_format_fields_id,
GROUP_CONCAT(sfbf.field_text SEPARATOR ', ') AS bformat,
SUM(sfbf.field_value) AS score_bstyle
FROM synt_format sfb
INNER JOIN `fields` sfbf ON sfbf.field_id = sfb.synt_format_fields_id
GROUP BY sfb.synt_format_lang_data
)
lbsf ON lbsf.synt_format_lang_data = lrel.lang_rel_b_id
GROUP BY lrel.lang_rel_id
Maybe a bit long, but output is exactly what was needed :-)

Optimising MySQL Query, Select within Select, Multiple of same

I need help optimising this MySQL statement that I whipped up. It does exactly what I want, however I have a great feeling that it'll be quite slow, since I do multiple selects within the statement, and I also query achievements_new multiple times. This is the first time I do some major statement like this, I'm used to the simple SELECT FROM WHERE style crap.
I might do some explaining, this is for a leaderboard style thing for my website.
--First variable output is a rank that is calculated according to the formula shown, (Log + Log + # of achievements).
--Wepvalue is the sum of the values of the weapons which that id has. playerweapons contains all the weapons, and weaponprices convert the type to the price, and then the SUM calculates the value.
--Achcount is simply the amount of achievements that's unlocked. Maybe this can be optimised somehow with the rank output?
--id in achievements_new and playerweapons are Foreign Keys to the id in playerdata
SELECT
(
IFNULL(LOG(1.5, cashearned),0) +
IFNULL(LOG(1.3, roundswon), 0) +
(
SELECT COUNT(*)
FROM achievements_new
WHERE `value` = -1 AND achievements_new.id = playerdata.id
)
) as rank,
nationality,
nick,
steamid64,
cash,
playtime,
damage,
destroyed,
(
SELECT SUM(price)
FROM weaponprices
WHERE weapon IN
(
SELECT class
FROM playerweapons
WHERE playerweapons.id = playerdata.id
)
) as wepvalue,
(
SELECT COUNT(*)
FROM achievements_new
WHERE `value` = -1 AND achievements_new.id = playerdata.id
) as achcount,
lastplayed
FROM playerdata
ORDER BY rank DESC
Table structures:
playerdata:
CREATE TABLE IF NOT EXISTS `playerdata` (
`id` int(11) unsigned NOT NULL,
`steamid64` char(17) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`nick` varchar(32) NOT NULL DEFAULT '',
`cash` int(32) unsigned NOT NULL DEFAULT '0',
`playtime` int(32) unsigned NOT NULL DEFAULT '0',
`nationality` char(2) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`damage` int(32) unsigned NOT NULL DEFAULT '0',
`destroyed` int(32) unsigned NOT NULL DEFAULT '0',
`cashearned` int(10) unsigned NOT NULL,
`roundswon` smallint(5) unsigned NOT NULL,
`lastplayed` datetime NOT NULL,
) ENGINE=InnoDB
achievements_new:
CREATE TABLE IF NOT EXISTS `achievements_new` (
`id` int(10) unsigned NOT NULL,
`achkey` enum(<snip - lots of values here>) NOT NULL,
`value` mediumint(8) NOT NULL DEFAULT '0'
) ENGINE=InnoDB
playerweapons:
CREATE TABLE IF NOT EXISTS `playerweapons` (
`id` int(10) unsigned NOT NULL,
`class` varchar(30) CHARACTER SET ascii NOT NULL
) ENGINE=InnoDB
weaponprices:
CREATE TABLE IF NOT EXISTS `weaponprices` (
`weapon` varchar(30) NOT NULL,
`price` int(10) unsigned NOT NULL
) ENGINE=InnoDB
Thanks in advance!
Try something like the query below.
I used LEFT JOIN instead of joins because there may be players without achievements or weapons. If you do not need these players you can use JOIN
SELECT
IFNULL(LOG(1.5, p.cashearned),0) +
IFNULL(LOG(1.3, p.roundswon), 0) +
SUM(CASE WHEN ac.id IS NOT NULL THEN 1 ELSE 0 END)/COUNT(pw.id) as rank
p.nationality,
p.nick,
p.steamid64,
p.cash,
p.playtime,
p.damage,
p.destroyed,
--SUM(CASE WHEN pw.id IS NOT NULL THEN pw.price ELSE 0 END) as wepvalue,
--wpn.price as wepvalue,
SUM(CASE WHEN pw.id IS NOT NULL THEN wp.price ELSE 0 END)/COUNT(ac.id) as wepvalue,
SUM(CASE WHEN ac.id IS NOT NULL THEN 1 ELSE 0 END)/COUNT(pw.id) as achcount,
lastplayed
FROM playerdata as p
JOIN playerweapons as pw ON pw.id = p.id
JOIN weaponprices as wp ON pw.class = wp.weapon
LEFT JOIN achievements_new as ac ON ac.id = p.id AND ac.value = -1
--LEFT JOIN playerweapons as pw ON pw.id = p.id
--LEFT JOIN weaponprices as wp ON pw.class = wp.weapon
--LEFT JOIN ( SELECT
--pw.id as player,
--SUM(wp.price) as price
--FROM weaponprices as wp
--JOIN playerweapons as pw ON pw.class = wp.weapon
--GROUP BY pw.id
--) as wpn ON wpn.player = p.id
GROUP BY
p.nationality,
p.nick,
p.steamid64,
p.cash,
p.playtime,
p.damage,
p.destroyed,
p.lastplayed
Your query is fairly reasonable, although I would rewrite the subqueries to use explicit joins rather than in and factor out the achievements subquery:
SELECT (IFNULL(LOG(1.5, cashearned),0) + IFNULL(LOG(1.3, roundswon), 0) +
coalesce(an.cnt, 0)
) as rank,
nationality, nick, steamid64, cash, playtime, damage, destroyed,
(SELECT SUM(wp.price)
FROM weaponprices wp JOIN
playerweapons pw
on pw.class = wp.weapons
WHERE pw.id = pd.id
) as wepvalue,
coalesce(an.cnt, 0) as achcount,
lastplayed
FROM playerdata pd left outer join
(SELECT id, count(*) as cnt
FROM achievements_new an
WHERE an.`value` = -1
GROUP BY an.id
) an
on an.id = pd.id
ORDER BY rank DESC;
For this query, create the following indexes:
playerweapons(id, weapon);
weaponprices(class, price);
achievements_new(value, id);
This does the following things:
It eliminates two redundant subqueries on achievements_new.
It should optimize the prices subquery to only use indexes.
It replaces the in with an explicit join, which is sometimes optimized better.
It does not require an outer group by.
I would try to remove all correlated subqueries
SELECT
( COALESCE(LOG(1.5, pd.cashearned), 0)
+ COALESCE(LOG(1.3, pd.roundswon), 0)
+ COALESCE(an.cnt, 0)) AS rank
, pd.nationality
, pd.nick
, pd.steamid64
, pd.cash
, pd.playtime
, pd.damage
, pd.destroyed
, COALESCE(pw.wepvalue, 0) AS wepvalue
, COALESCE(an.cnt, 0) AS achcount
, pd.lastplayed
FROM playerdata pd
LEFT JOIN (
SELECT
id
, COUNT(*) AS cnt
FROM achievements_new
WHERE value = -1
GROUP BY
id
) an
ON pd.id = an.id
LEFT JOIN (
SELECT
playerweapons.id
, SUM(price) AS wepvalue
FROM weaponprices
INNER JOIN playerweapons
ON weaponprices.weapon = playerweapons.class
GROUP BY
playerweapons.id
) pw
ON pd.id = pw.id
ORDER BY
rank DESC;

MySQL Invalid Use of Group Function

I'm getting Error Code: 1111. Invalid use of group function when trying to build a query in MySQL. Apparently MySQL doesn't support WITH, which is what I'm more comfortable using.
SELECT DISTINCT `UserID`
FROM `user`
INNER JOIN `message`
ON `user`.`Message` = `message`.`Recipient`
WHERE MAX(`TotalSize`) IN (
SELECT SUM(`message`.`Size`) as `TotalSize`
FROM `message`
INNER JOIN `category`
ON `message`.`CatID` = `category`.`CatID`
WHERE `category`.`CatName` = 'Inbox'
GROUP BY `Recipient`);
SELECT `UserID`, MAX(SUM(message.Size)) as TotalSize
FROM `user`
INNER JOIN `message`
ON `user`.`Message` = `message`.`Recipient`
INNER JOIN category
ON message.CatID = category.CatID
WHERE category.CatName = 'Inbox'
GROUP BY UserID
You need to use HAVING clause instead of WHERE MAX(TotalSize)
SELECT DISTINCT `UserID`
FROM `user`
INNER JOIN `message`
ON `user`.`Message` = `message`.`Recipient`
GROUP BY `UserID`
HAVING MAX(`message`.`Size`) IN (
SELECT SUM(`message`.`Size`) as `TotalSize`
FROM `message`
INNER JOIN `category`
ON `message`.`CatID` = `category`.`CatID`
WHERE `category`.`CatName` = 'Inbox'
GROUP BY `Recipient`);
Group functions are not accessible in WHERE clause , HAVING can filter on aggregates.

Check in MySQL table if my ID exist in the results

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