In a table that has the columns: 'product_id', 'price', ... (and others). I need to obtain the record with the lowest and unique price for a given product_id.
I tried different sentences without having the expected result. Finally I came across this sentence (for product_id = 2):
SELECT `price` , `product_id`
FROM bids
WHERE `product_id` = 2
GROUP BY `price`
HAVING COUNT( `price` ) = 1
ORDER BY `price`
LIMIT 1;
But it seems not to be an elegant solution having recourse to LIMIT and ORDER. How can I obtain the same record using the MIN() function or even something else?
This should work because you are already specifying the product_id to analyze:
SELECT MIN(t1.price) AS price, t1.product_id
FROM
(
SELECT price, product_id
FROM bids
WHERE product_id = 1
GROUP BY price, product_id
HAVING COUNT(price) = 1
) t1
Notes: MIN/MAX vs ORDER BY and LIMIT
Skydreamer, I'm not sure but as I understand it the op wants the the first unique value.
If the prices are 1,1,2,2,3 the query should return the row with the price of 3.
Related
I'm stuck on trying to write this query, I think my brain is just a little fried tonight. I have this table that stores whenever a person executes an action (Clocking In, Clocking Out, Going on Lunch, Returning from Lunch) and I need to return a list of all the primary ID's for the people who's last action is not clock_out - but the problem is it needs to be a somewhat fast query.
Table Structure:
ID | person_id | status | datetime | shift_type
ID = Primary Key for this table
person_id = The ID I want to return if their status does not equal clock_out
status = clock_in, lunch_start, lunch_end, break_start, break_end, clock_out
datetime = The time the record was added
shift_type = Not Important
The way I was executing this query before was finding people who are still clocked in during a specific time period, however I need this query to locate at any point. The queries I am trying are taking the thousands and thousands of records and making it way too slow.
I need to return a list of all the primary ID's for the people whose last action is not clock_out.
One option uses window functions, available in MySQL 8.0:
select id
from (
select t.*, row_number() over(partition by person_id order by datetime desc) rn
from mytable t
) t
where rn = 1 and status <> 'clock_out'
In earlier versions, one option uses a correlated subquery:
select id
from mytable
where
datetime = (select max(t1.datetime) from mytable t1 where t1.personid = t.person_id)
and status <> 'clock_out'
After looking through it further, this was my solution -
SELECT * FROM (
SELECT `status`,`person_id` FROM `timeclock` ORDER BY `datetime` DESC
) AS tmp_table GROUP BY `person_id`
This works because it is grouping all of the same person ID's together, and then ordering them by the datetime and selecting the most recent.
I'm doing a basic SQL select query which returns a set of results. I want a specific row which the entry "Fee" to be put at the top of the results, then the rest.
Something like:
SELECT * FROM tbl ORDER By Charges = Fee DESC, Charges DESC
Can anyone help?
You could try this :
SELECT * from tbl ORDER BY CASE WHEN Charges = 'Fee' THEN 0 ELSE 1 END, Charges DESC;
I think you'd have a use a UNION query. ORDER BY doesn't support this kind of thing by default as far as I know.
Something like this:
SELECT * FROM tbl WHERE Charges = 'Fee'
UNION
SELECT * FROM tbl ORDER BY Charges DESC
You would have to use ORDER BY with a FIELD attribute, which would then order by those first.
As I don't have your table definitions, I have throw one together here http://sqlfiddle.com/#!9/91376/13
For sake of it disappearing, the script pretty much consists of;
CREATE TABLE IF NOT EXISTS `tbl` (
`id` int(6) unsigned AUTO_INCREMENT,
`Name` char(6) not null,
`Charges` char(10) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `tbl` (`Name`, `Charges`)
VALUES ('One', 'Fee'), ('Two', 'Charge'), ('Three', 'Charge'),
('Four', 'Charge'), ('Five', 'Fee'), ('Six', 'Fee'),
('Seven', 'Invoice'), ('Eight', 'Fee'), ('Nine', 'Invoice'),
('Ten', 'Invoice');
SELECT *
FROM tbl
ORDER BY FIELD(`Charges`, 'Charge') DESC
;
Which returns:
id Name Charges
2 Two Charge
3 Three Charge
4 Four Charge
1 One Fee
9 Nine Invoice
8 Eight Fee
7 Seven Invoice
6 Six Fee
5 Five Fee
10 Ten Invoice
So, to directly answer your question, your query would be;
SELECT *
FROM tbl
ORDER BY FIELD(Charges, 'Fee') DESC
edit : Viewable, sorted by Charges = Fee here : http://sqlfiddle.com/#!9/91376/15
SELECT * FROM tbl ORDER By FIELD(Charges, 'Fee') DESC
You can use something like the above. Where Charges is the field and fee the specific value. That way you can keep it simple.
I'm grouping results by SERIAL_NUMBER and I'd like to display the last records for each group according to record ID DESC this what I've got so far:
SELECT * FROM
(SELECT `SERIAL_NUMBER`, `PART_NUMBER` , `POSITION` , `DUE_CAP_CHECK_DATE` , `DUE_OVERHAUL_DATE`
FROM `history_card` ORDER BY `HISTORY_ID` DESC ) AS X
GROUP BY `SERIAL_NUMBER`
But It does not return the last record, it returns the first one ;(
You are misusing the heinously confusing nonstandard MySQL extension to GROUP BY. Read this. https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html (This extension is like a talking horse. We don't wonder that it works badly. We wonder that it works at all.)
You can get the latest (largest) value of HISTORY_ID for each value of SERIAL_NUMBER from your table like this:
SELECT MAX(HISTORY_ID) FROM history_card GROUP BY SERIAL_NUMBER
Then you can use that set of HISTORY_ID values to retrieve what you want from your table.
SELECT SERIAL_NUMBER, PART_NUMBER, POSITION, DUE_CAP_CHECK_DATE, DUE_OVERHAUL_DATE
FROM history_card
WHERE HISTORY_ID
IN (SELECT MAX(HISTORY_ID) FROM history_card GROUP BY SERIAL_NUMBER)
Accept my best wishes dear friends, I have a problem related with mysql table. Actually I've a table like this
Now I want to query last purchase tax for every product code. for this i use this mysql query :
SELECT DISTINCT PROD_CODE, PURCHASE_TAX
FROM PRODUCT_STOCK
WHERE PROD_CODE
IN ( 5300, 'BLUEBOOK' )
ORDER BY ID DESC
LIMIT 0 , 30
from doing this mysql returning result set like this
As you can see in result set mysql return all row of related product. while i want only last row. Please help me for this
Since I see no column to show time, I am assume all the records are inserted in serial order, hence greater the id, the more recent the record is.
SELECT DISTINCT(PROD_CODE) AS CODE, (SELECT PRODUCT_STOCK.PURCHASE_TAX FROM PRODUCT_STOCK WHERE PRODUCT_STOCK.PROD_CODE = CODE ORDER BY ID DESC LIMIT 1) AS PURCHASE_TAX
FROM PRODUCT_STOCK
WHERE PROD_CODE
IN ( 5300, 'BLUEBOOK' );
Try with GROUP BY like this
SELECT DISTINCT PROD_CODE, PURCHASE_TAX
FROM PRODUCT_STOCK
WHERE PROD_CODE
IN ( 5300, 'BLUEBOOK' )
GROUP BY PROD_CODE;
I have a database in MYSQL and it has chat table which looks like this.
I am using this query for fetching these records
SELECT * FROM (
SELECT * FROM `user_chats`
WHERE sender_id =2 OR receiver_id =2
ORDER BY id DESC
) AS tbl
GROUP BY sender_id, receiver_id
But my requirement is only 5,4 ID's records. basically my requirement id fetching last conversation in between 2 users. Here in between 2 & 3 user conversation has 2 records and we want only last one of them i.e. id = 5, here don't need id = 2.
So how we can write a query for that result?
SELECT
*
FROM
user_chats uc
WHERE
not exists (
SELECT
1
FROM
user_chats uc2
WHERE
uc2.created > uc.created AND
(
(uc.sender_id = uc2.sender_id AND uc.reciever_id = uc2.reciever_id) OR
(uc.sender_id = uc2.reciever_id AND uc.reciever_id = uc2.sender_id)
)
)
The following gets you latest record (assuming that the bigger id, the later it was created) meeting your criteria:
SELECT * FROM `user_chats`
WHERE (`sender_id` =2 AND `receiver_id` =3) OR (`sender_id` =3 AND `receiver_id` =2)
ORDER BY `id` DESC
LIMIT 1
which would be a good idea, if id is primary key and it rises along with rising value of created. Otherwise (if you are not sure that id rises when created rises) replace ORDER BY line with the following:
ORDER BY `created` DESC
Plus, in both cases, put proper indexes on: id (if it is your primary key, then there is no need to put additional index on it), sender_id and receiver_id (preferably composite index, meaning the single index for both columns), created (if you want to use ORDER BY created DESC instead of ORDER BY id DESC - otherwise there is no need for that).
try GROUP BY LEAST(sender_id, receiver_id), GREATEST(sender_id, receiver_id)