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.)
Related
I encountered a problem on a database I am working with. I have a table of counsels which may hold repeating values, but their is an enrolment number filed which is unique and can be used to fetch them. However, I want to join from a cases_counsel table on the "first" unique value of the counsel table that matches that column on the cases counsel table.
I want to list the cases belonging to a particular counsel using the enrolment_number as the counsel_id on the cp_cases_counsel table. That means I want to pick just a distinct value of a counsel, then use it to join the cp_cases_counsel table and also return the count for such.
However, I keep getting duplicates. This was the mysql query I tried
SELECT T.suitno, T.counsel_id, COUNT(*) as total from cp_cases_counsel T
INNER JOIN (SELECT
enrolment_number as id, MIN(counsel)
FROM
cp_counsel
GROUP BY
enrolment_number
) A
ON A.id = T.counsel_id
GROUP BY T.suitno, T.counsel_id
and
SELECT enrolment_number as id, MIN(counsel) as counsel, COUNT(*) as total FROM cp_counsel
JOIN cp_cases_counsel ON cp_cases_counsel.counsel_id = cp_counsel.enrolment_number
GROUP BY enrolment_number
For the second query, it's joining twice and I am having like double of what I am supposed to get.
The columns that you want in the results are councel (actually only one of all its values) from cp_counsel and counsel_id from cp_cases_counsel, so you must group by them and select them:
SELECT a.counsel, t.counsel_id, COUNT(*) AS total
FROM cp_cases_counsel t
INNER JOIN (
SELECT enrolment_number, MIN(counsel) AS counsel
FROM cp_counsel
GROUP BY enrolment_number
) a ON a.enrolment_number = t.counsel_id
GROUP BY a.counsel, t.counsel_id;
I have two table with one to many relationship. One is header and the other is detail.
Header Table Columns are State, Item, Bill, Quantity
Detail Table Columns are Header_ID, Allocated To, Allocated Quantity
I need to get the sum of Header Quantity and Sum of Detail Quantity using left join as detail may not exists sometime.
Here is how it looks after joining (Before grouping)
My required result after grouping should be
State, Item, Total Quantity (Header), Total Allocated (Detail Quantity).
But my problem is i am doing left join so header value is repeating, when i sum the duplicate values are also summing up.
Here is the Query i tried
SELECT
a.State,
a.Item,
b.Allocated,
sum(a.Quantity) AS Header_Total, -- Should take unique/single
sum(b.Quantity) AS Detail_Taol
FROM table1 a
LEFT JOIN table2 b ON a.ID = b.Header_ID
GROUP BY
a.State,
a.Item,
b.Allocated;
Please help in querying this to get the desired result.
JOIN (including LEFT JOIN) creates a result set containing all pairs of rows allowed by the ON clause. So your SUM(a,Quantity) expression adds up multiple copies of that value and so generates wrong results in a lot of cases.
This is sometimes called a combinatorial explosion or a cardinality error.
Fix: take off the SUM and add a.Quantity to the GROUP BY.
SELECT
a.State,
a.Item,
b.Allocated,
a.Quantity AS Header_Total,
sum(b.Quantity) AS Detail_Taol
FROM table1 a
LEFT JOIN table2 b ON a.ID = b.Header_ID
GROUP BY
a.State,
a.Item,
b.Allocated,
a.Quantity;
I am working on product data, part of which has the below structure (let's call it product_serials):
The table is a collection of product serial numbers. The snapped field determines whether a specific product has been purchased or not via it's serial number. Am trying to query the table to get a count of both all serials and also all unpurchased serials of the same product_id, using a single SQL query. So far using COUNT(ps1.id) AND COUNT(ps2.id) ... WHERE ps2.snapped = FALSE does not seem to work, it still counts the same values for both all serials and unpurchased serials, and even exaggerates the count, so am definitely doing something wrong.
What could I be missing?
My SQL query as requested:
SELECT pd.id AS product_id, pd.description,
COUNT(pds.id) AS total, COUNT(pds2.id) AS available
FROM products pd
LEFT JOIN product_serials pds ON pds.product_id = pd.id
LEFT JOIN product_serials pds2 ON pds2.product_id = pd.id
WHERE pds2.snapped = FALSE
GROUP BY pd.id
ORDER BY pd.date_added DESC
Here you join tables (even multiplying them) and then apply a WHERE condition to both.
I suggest something like the following:
SELECT product_id, count(serial), count(unpurchased)
FROM (SELECT product_id, serial,
CASE WHEN snapped THEN NULL ELSE 1 END AS unpurchased)
GROUP BY product_id
I have 2 tables, one containing tickets and the other routes. I want to produce 2 attributes, flight_DATE and route_CODE, for the greatest numbers of tickets sold. Since there is no attribute that stores the number of tickets sold I have to perform a query finding the max() on the number of count(ticket_ID), as each ticket_ID represents a ticket sold... right? I have no actual database to try this out so that's my query:
SELECT routes.ROUTE_CODE , tickets.FLIGHT_DATE
FROM routes JOIN tickets ON routes.ROUTE_CODE = tickets.ROUTE_CODE
WHERE count(ticket.TICKET_ID) = (
SELECT max(count(ticket.TICKET_ID)
)
I am not so confident with SQL so is this even correct??? thanks in advance!
The idea behind your query is correct, but you wrote the max calculation without a level, so you will get the count of all the tickets sold.
You also cannot put in your where clause a condition on an aggregated column (as you did with count(ticket.TICKET_ID); that kind of condition goes to the having clause.
This one should do what you need
SELECT ROUTE_CODE, FLIGHT_DATE
JOIN tickets
GROUP BY ROUTE_CODE , FLIGHT_DATE
HAVING count(tickets.TICKET_ID) = ( /*filter the row with count = max count */
SELECT max(CNT) /* get the max of the counts */
FROM (
SELECT count(TICKET_ID) as CNT /* get the counts at desired levels */
FROM tickets
GROUP BY FLIGHT_DATE, ROUTE_CODE
)
)
I removed the join with routes table because the only column you were using (ROUTE_CODE) is available on the tickets table too, but that may be useful if you want to select more data from that table and definitely was not an error.
BTW, if you don't have a database available for testing, you can try your queries on sites like rextester
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);