Take the below for example:
SELECT
*
FROM
auctions AS a
LEFT JOIN winners AS w ON a.auction_id=w.auction_id
WHERE
a.active=1
AND
a.approved=1
GROUP BY
a.auction_id
ORDER BY
a.start_time DESC
LIMIT
0, 10;
Sometimes this may match multiple results in the winners table; I don't need both of them, however I want to have control over which row I get if there are multiple matches. How can I do an ORDER BY on the winners table so that I can make sure the row I want is the first one?
It is difficult to accurately answer without seeing your table structure but if your winners table has a winner date column or something similar, then you can use an aggregate function to get the first record.
Then you can return the record with that earliest date similar to this:
SELECT *
FROM auctions AS a
LEFT JOIN winners w1
ON a.auction_id=w1.auction_id
LEFT JOIN
(
select auction_id, min(winner_date) MinDate -- replace this with the date column in winners
from winners
group by auction_id
) AS w2
ON a.auction_id=w2.auction_id
and w1.winner_date = w2.MinDate
WHERE a.active=1
AND a.approved=1
ORDER BY a.start_time DESC
SELECT *
FROM auctions AS a
LEFT JOIN (select auction_id from winners order BY auction_id limit 1) AS w ON a.auction_id = w.auction_id
WHERE a.active = 1
AND a.approved = 1
GROUP BY a.auction_id
ORDER BY a.start_time DESC
Change the reference to the winners table in the join clause to a sub-query. This then gives you control over the number of records returned, and in what order.
Related
I want to select the last inserted date and at the same time I want to select the user-name and count how many times the user-profile is visited.
So I am using this query
SELECT v.visitor_date, i.info_name, count(DISTINCT v.visitor_date) AS counted
FROM profile_visitors v
INNER JOIN profile_info i ON i.info_userId = v.visitor_accountId
ORDER BY v.visitor_date DESC
LIMIT 1
The result of the fiddle is wrong and SHOULD be
2015-07-28 11:05:16 - Testname - 5
Anyone knows what is wrong with the query?
http://sqlfiddle.com/#!9/2814c/1
DISTINCT does NOT give you the first or last record of any group, in fact you cannot guarantee which record DISTINCT will display within a group (nor does this matter by the way). So select MAX visitor date.
Try below query
SELECT MAX( v.visitor_date ) , i.info_name, COUNT( DISTINCT v.visitor_date ) AS counted FROM profile_visitors v INNER JOIN profile_info i ON i.info_userId = v.visitor_accountId ORDER BY v.visitor_date DESC LIMIT 1
You can try it:
SELECT v.visitor_date,
i.info_name,
COUNT(*) AS counted
FROM profile_visitors v
INNER JOIN profile_info i ON i.info_userId = v.visitor_accountId
GROUP BY v.visitor_accountId
ORDER BY v.visitor_date DESC
LIMIT 1
I am saving the history of Facebook likes for a page, identified by user_id.
Now from this table, I need to get a set representing the user_id's and their latest number of likes, based on the most recent timestamp.
I started off with this:
SELECT *
FROM facebook_log
GROUP BY user_id
ORDER BY timestamp DESC;
But that does not do what I want because it returns the first records with the lowest timestamps.
I read something online about GROUP returning the very first records from the table.
I also understood something about JOIN the table with itself, but that doesn't work either, or I did something wrong.
If you just need the user_id and the timestamp, you can just do
select f.user_id, max(f.timestamp)
from facebook_log
group by user_id;
if you need all the data from the table, you can do
select f.*
from facebook_log f
inner join (select max(timestamp) mt, user_id
from facebook_log
group by user_id) m
on m.user_id = f.user_id and m.mt = f.timestamp
You can also get the latest number of likes by using this MySQL trick:
select f.user_id, max(f.timestamp),
substring_index(group_concat(f.numlikes order by f.timestamp desc), ',', 1) as LatestLikes
from facebook_log f
group by f.user_id;
I'm trying to write a query that will find all rows in a group EXCEPT the row with the max value. I have a query so far that finds the row with the max value, but now I need to find all the rest of the rows. Here is a SQLFiddle with the two databases and sample data. I also have the query that finds the max rows.
http://sqlfiddle.com/#!2/514d2/33
For those that don't want to use SQLFiddle...
Tablename: listings
Tablename: bids
SELECT listings.end_date, listings.user_id, listings.title,
listings.auc_fp, listings.id, listings.auc_image1
FROM listings
JOIN bids b1
ON b1.listing_id=listings.id
LEFT JOIN bids b2
ON b2.listing_id=listings.id AND b1.bid < b2.bid
WHERE b1.user_id = 1
AND b2.bid IS NULL
AND listings.end_date > NOW()
ORDER BY listings.list_ts DESC
Above is the query that find the max rows. I'm trying to join the listings table with the bids table on listings.id=bids.listing_id. Then I need to find all the rows where a user ($user or user "1") has bid on that listing. Then I need to exclude the listings where the user is has the max bid (which is what the query above does).
I originally thought I could use the query above as a subquery to exclude the listings where the user is the max bidder. But I'm not sure if that's the best way to do it and I'm not that good with subqueries.
Note that answer was revised several times based on the comments below.
SELECT
lst.end_date,
lst.title,
lst.auc_fp,
lst.id as listing_id,
lst.auc_image1,
b.user_id as bid_user_id,
b.bid as bid_amount,
maxbids.maxbid as maxbid_for_listing
FROM listings lst
INNER JOIN
(
SELECT listing_id, MAX(bid) maxbid
FROM bids b
GROUP BY listing_id
) maxbids ON lst.id = maxbids.listing_id
INNER JOIN bids maxusers ON maxusers.bid = maxbids.maxbid AND maxusers.listing_id = maxbids.listing_id
INNER JOIN bids b ON
maxbids.listing_id = b.listing_Id AND
b.bid < maxbids.maxbid AND
b.user_id <> maxusers.user_id
WHERE lst.end_date > NOW()
ORDER BY lst.list_ts DESC
I've got query like:
SELECT
b.title,
b.url,
b.`date`,
b.gallery,
count(c.id) as comments_count,
a.name,
b.content,
b.comments,
LEFT(b.content, LOCATE('<page>', b.content)-1) as content_short
FROM blog b
LEFT JOIN blog_comments c ON
(b.id = c.note AND c.approved = 1)
LEFT JOIN administrators a ON
(b.aid = a.id)
WHERE
b.`date` < now() AND
b.active = 1
ORDER BY b.`date` DESC;
Now, when I remove count(c.id) as comments_count,, I've got 2 rows returned. When it's present, there's only 1 row returned.
Is there some way to fix ot or I simply have to change
count(c.id) as comments_count, to (select count(id) ascomments_countfrom blog_comments where note = b.id) as comments_count,?
Count(*) is an aggregated function, so it will apply in a group.
That means that when you count on groups, it will apply the function on every group.
The groups are formed when you use Group By, in this case, you're not using, so MySQL consider that ALL select (your joins) is ONLY 1 GROUP.
So, applies the count on the unique group and returning the count of rows.
you should add a Group by by the field you want
An example is here
I have this php/sql Query:
$result = mysql_query("
SELECT r.item_id, AVG(rating) AS avgrating, count(rating) AS count, i.item, c.category
FROM ratings AS r
LEFT JOIN items AS i
ON r.item_id = i.items_id
INNER JOIN master_cat c
ON c.cat_id = i.cat_id
GROUP BY item_id
ORDER BY avgrating DESC
LIMIT 25;");
When I output this, count is correct, it shows how much votes certain items have received.
I simply want to add a WHERE count >= 10 clause but everything breaks. Obviously, when there are thousands of items, some will get one vote and have 100%. But that is not a good indicator. I want to print out items that have at least 10 votes (or count >= 10)
You should to use having instead where
SELECT
r.item_id, AVG(rating) AS avgrating,
count(rating) AS count, i.item, c.category
FROM
ratings AS r
LEFT JOIN items AS i
ON r.item_id = i.items_id
INNER JOIN master_cat c
ON c.cat_id = i.cat_id
GROUP BY
item_id
HAVING
count >= 10
ORDER BY
avgrating DESC
LIMIT 25;
You can't use a where filter on the results of an aggregate function (count()). where is applied at the row-level, as the DB is deciding whether to include the row or not in the result set - at this point the results of the count aren't available yet.
What you want is a having clause, which is applied as one of the last steps before results are sent to the client, after all the aggregate results have been calculated.
...
GROUP BY item_id
HAVING count > 10
ORDER BY ...
you need to tell it what you want to count
having count(*) > 10