Trying to join table on the row with a max value - mysql

I feel like I need to use a sub-query but I'm having trouble getting the query to work right
As a scenario, I have an auction_item that has bids on it, there are three bids.
I want to get just the user information for the highest bid on that item.
The info I have is the item_id, so I need to look up bids on that item id, and join the user table on the user_id of the bid row with the highest bid for that item.
SELECT user.* FROM text2bid_users AS user
INNER JOIN (SELECT user_id,MAX(bid_amt) FROM text2bid_bids
WHERE item_id = 11479) AS bid
ON user.user_id = bid.user_id
Problem is it's returning the first row from bids instead of the one with the max bid_amt
Hoping someone can point me in the right direction here

Try the following Query:
select user.* from text2bid_users as user
where user.user_id =(select user_id from text2bid_bids
where item_id = 11479
order by bid_amt desc limit 1);

Related

SQL query is not retrieving all the fields

I have to tables in my database, the first one (participants) look just like that:
And I have another called votes in which I can vote for any participants.
So my problem is that I'm trying to get all the votes of each participant but when I execute my query it only retrieves four rows sorted by the COUNT of votes, And the other remaining are not appearing in my query:
SELECT COUNT(DISTINCT `votes`.`id`) AS count_id, participants.name
AS participant_name FROM `participants` LEFT OUTER JOIN `votes` ON
`votes`.`participant_id` = `participants`.`id` GROUP BY votes.participant_id ORDER BY
votes.participant_id DESC;
Retrieves:
I think the problem is that you're grouping by votes.participant_id, rather than participants.id, which limits you to participants with votes, the outer join notwithstanding. Check out http://sqlfiddle.com/#!2/c5d3d/5/0
As what i have understood from the query you gave you were selecting unique id's from the votes table and I assume that your column id is not an identity. but it would be better if that would be an identity? and if so, here is my answer.replace your select with these.
Select count (votes.participant.id) as count_id ,participants.name as participant_name
from participants join votes
on participants.id = vote.participant_id
group by participants.name
order by count_id
just let me know if it works
cheers

Select max with group by on other table

I have 2 tables: users_item that has 2 columns user_id, item_id and item_rates that has 2 columns rate_item_id, rate.
They are connected with Foreign_Key on users_item.item_id = item_rates.rate_item_id. I need to
select item_id's with max rate for a given range of users. One user can have a lot of items.
My select is:
SELECT MAX(rate), rate_item_id, user_id
FROM users_item JOIN item_rates ON item_id = rate_item_id
AND user_id in (2706,2979) GROUP BY user_id;
but it returns not correspondent item_id's with max rate. In given example select has to return just 2 rows. Can someone help on this. Thanks in advance.
Ok, I found what you want.. Try this:
SELECT users_item.user_id, item_id, maxrate
FROM user_items
JOIN item_rates ON users_item.item_id = item_rates.rate_item_id
JOIN (SELECT MAX(rate) AS maxrate, user_id
FROM users_item JOIN item_rates ON item_id = rate_item_id
WHERE user_id in (1,2)
GROUP BY user_id) AS maxis
ON users_item.USER_ID = maxis.USER_ID
WHERE item_rates.rate = maxrate
The reason you need a subquery is that multiple different items own by the same user could have the same rate and this could be the maximum rate of user's owned items.
Try grouping by user_id, rate_item_id
I'm surprised that MySql doesn't give you an error, Oracle would...

Correct SELECT/JOIN for "has login user liked"

We're having the following tables:
User (id, name)
Item (id, title, text)
Like (id, itemId, userId)
The Like table stores a has-and-belongs-to-many relationship between Item and User.
What is the most efficient way to select a list from Item and see if the "logged in" user has "liked" that particular Item?
SELECT * FROM Item ORDER BY published DESC LIMIT 10
(+ check if each Item has been liked by known user id, e.g. '123')
Is this done best with a sub-select, join or two individual queries?
The most straight forward way ( if i have understood the question right ) is
select * from Like where itemId = ? and userId = ?;
Assuming you have the itemId you want to check and userId from the session.
It will be good to have a composite index on table Like and columns itemId,userId to have fast returning queries.
Joining is more effective than subselect, database engines are well optimized for joining tables.
The query (I have changed the name of table 'like', because it is a keyword in SQL)
SELECT COUNT(*)
FROM User u
JOIN Likes l ON u.id = l.userID
JOIN Item i ON l.itemid = i.id
WHERE i.title = 'item' AND u.name = 'user'
If the result is greater than 0, the user liked the item.
EDIT:
If you want to display the 10 newest items, and see if the user liked them or no, you can use this query:
SELECT i.id, i.title, IF(l.userID IS NULL, 0, 1) AS Liked
FROM item i
LEFT JOIN Likes l ON i.id = l.itemID AND l.userID = ?
ORDER BY i.published DESC LIMIT 10
It is important to use LEFT JOIN, otherwise you will not get the rows the user has not liked.

is it possible to have group by sort in any order other than ascending?

I have a query that joins a couple of tables and produces a lot of rows, in a situation where I only wish to see one row per user. I have solved the "only one user" problem by using group by user.id, however, I'm noticing that now for each user I get the values from the joined table that represent the first entry (rather than the last).
so in other words
user:
id | phone
item:
id | user_id | timestamp
my intention is to join these tables and select the latest item (based on timestamp, or item.id desc) but to only get one item per user (rather than see all the items that each user has). group by user.id solves the problem of giving me just one item per user, but they always turn up with the first item that has the lowest item.id, whereas I want the most recent one.
Is there a better way to achieve this... I was initially noodling with distinct but that doesn't seem to do the trick.
TIA
[EDIT]
In response to Jocelin's question below:
select user.id, item.timestamp from item join user on user.id = item.user_id order by user.id
mysql has a "cheat" for getting the first row only of each group:
select *
from (select
u.id as user_id,
u.name,
i.id as item_id,
i.timestamp
from user u
join item i on i.user_id = u.id
order by timestamp desc -- "desc" = order descending
) x
group by user_id
The "cheat" is that mysql allows you not aggregate the non-group by columns (unlike every other database I know). Instead of giving an SQL syntax error, it returns the first record only of each group. Not SQL standard, but very handy.
The beauty of this is that you don't need any correlated subqueries, which are dreadfully slow.
The inner query is used to order the records in timestamp latest-first order, so the first record encountered for each user is the "most recent".
Use an ORDER BY with DESC clause:
select
user.id, item.timestamp
from
item
join
user on user.id = item.user_id
group by
user.id
order by
user.id DESC
I'm suspecting (from your comments below) that your issue isn't really what you describe. Try something like this instead (untested, because I don't use MySQL - it works in SQL Server and SQLite):
select
user.id, i.ts
from
(select id, max(timestamp) as ts from items group by id) i
join
user u on u.id = i.id
You will need to use a JOIN. First create a subselect grouping by user and selecting the MAX of timestamp. This gets you one row per user, with the latest entry (and loses all other fields).
Then join it back using the timestamp in the JOIN expression, to restore the missing fields.
Sorry, but without the table schema it isn't easy to be more specific than this. Hope that the JOIN reference points you in the right direction to modify your query.

MySQL Join with Highest?

I have two tables, one called items and one called bids. Bids contains a bunch of bids with an item_id. I am trying to get all the information on the item with the associated highest bid.
I tried doing something like
SELECT * FROM items JOIN bids ON items.id=bids.item_id GROUP BY item_id
However that seems to return the first bid, not the highest.
How could I get the highest?
You need to use a subquery to discover the maximum bid value, then join that with your existing query to obtain all of the desired output data. Assuming that the bid value is in a column called value, and that the PK of the bids table is a column called id:
SELECT items.*, bids.*
FROM
items
JOIN (
SELECT id, item_id, MAX(value) AS value FROM bids GROUP BY item_id
) AS maxbids ON items.id = maxbids.item_id
JOIN bids ON bids.id = maxbids.id
GROUP BY items.id
If there are multiple bids of the maximum amount, this query will return all of them.
A self-join will also do it, I think. So, assuming (as #eggyal did) that there's a bids.value column:
SELECT *
FROM items i
JOIN bids b1 ON b1.item_id=i.id
JOIN bids b2 ON b2.item_id=i.id AND b2.value>b1.value
WHERE b2.id IS NULL
But that will return multiple rows if there are mutiple bids for the same amount. How do you want to handle them?
(And that SELECT * should be narrowed down.)