adding sequential number to existing data specific to an ID MySQL - mysql

New to the forum.I wonder if somebody out there might be able to help with an issue I am having?
I need to add an addition column in a query to show a sequential number 1,2,3...ect but to have it be specific to an existing ID - The s_id based on the order of the s_id. Below show an example of the data I am working with.
'p_id' 's_id'
'327' '569'
'330' '569'
'1205' '569'
'350' '1000'
I am aiming to get it to look like this.
'Seq_no' 'p_id' 's_id'
'1' '327' '569'
'2' '330' '569'
'3' '1205' '569'
'1' '350' '1000'
I have looked at adding an auto increment bur cannot manage to tie it back to the back specifically to the s_id.
Any help would be greatly appreciated.
Best Regards
DSW

You can do it with a self join :
SELECT count(s.sid) as seq_no,t.p_id,t.s_id
FROM YourTable t
JOIN YourTable s
ON(t.s_id = s.s_id AND t.p_id >= s.p_id)
GROUP BY t.p_id,t.s_id

Assuming that you're sorting the dataset by (s_id,p_id) then here's one way (untested):
SELECT x.*
, CASE WHEN #prev = x.s_id THEN #i:=#i+1 ELSE #i:=1 END i
, #prev := s_id prev
FROM my_table x
, (SELECT #prev:=null,#i:=0) vars
ORDER
BY s_id,p_id;

A common approach is using MySQL user defined variables.
In your case you need two of them.
SELECT
#rn := IF(#sameSid = s_id, #rn := #rn + 1 ,
IF(#sameSid := s_id, 1, 1)
) AS Seq_no,
p_id,
s_id
FROM your_table
CROSS JOIN
(
SELECT #sameSid := 0, #rn := 1
) AS var
ORDER BY s_id , p_id

Related

Mysql session variable emulating row_num does not increase in value

Since MySql does not provide a row_num facility, I was trying to emulate its functionality using session variables (#variable_name) in my query
the problem statement is as follows
Given a table 'product_view' having columns 'productTitle' and 'categoryName',
select the first 2 products from each category whose title matches a provided string
Going by the following query
SELECT
#row_num := CASE
WHEN #cat_name = categoryName THEN #row_num + 1
ELSE 1
END
AS num,
#cat_name := categoryName AS categoryName,
productTitle
FROM product_search
WHERE
cityId = 1 AND
mainStatus= 'Active' AND
stock_status = 'In Stock' AND
prodQuantity != 0 AND
productTitle LIKE '%apple%'
ORDER BY categoryName, LOCATE('apple', productTitle), productTitle
This is expected to give row_num values 1,2 for category1 and 1,2 for category 2 and so on (wherever ther is a match for 'Apple').
But the rownum value is always stuck at 1
Something similar on the fiddle below
FIDDLE
Can someone please help me out on this
In more recent versions of MySQL, you need to do the order by in a subquery.
In addition, you cannot set #cat_name in one expression and use it in another. MySQL does not guarantee the order of evaluation of expressions in a SELECT. So, you don't know which gets evaluated first, the assignment or the comparison.
I usually write this as:
SELECT (#rn := IF(#cat_name = categoryName, #rn + 1,
IF(#cat_name := categoryName, 1, 1)
)
) as num,
categoryName, productTitle
FROM (SELECT ps.*
FROM product_search ps
WHERE cityId = 1 AND
mainStatus= 'Active' AND
stock_status = 'In Stock' AND
prodQuantity <> 0 AND
productTitle LIKE '%apple%'
ORDER BY categoryName, LOCATE('apple', productTitle), productTitle
) ps CROSS JOIN
(SELECT #cat_name := '', #rn := 0) params

Fetch last three orders from a table

Consider a table with the following columns:
Customer Email ID
Payment Method (COD/ Netbanking/ CreditCard/ DebitCard)
Order ID
Order Creation Date
Order Status(Success/ Failed/ Cancelled)
How do I fetch the last three successful orders past 3 months for each customer from these table in SQL along with the relevant details?
This is a bit painful in MySQL. Probably the simplest method is to use variables.
Your column names are not clear. And you have some additional conditions, but this is the basic idea:
select t.*
from (select t.*,
(#rn := if(#c = customerid, #rn + 1,
if(#c := customerid, 1, 1)
)
) as rn
from t cross join
(select #rn := 0, #c := '') params
order by customerid, orderdate desc
) t
where rn <= 3;
You can add the additional where conditions to the subquery.
I Hope this helps
SELECT *
FROM TABLENAME
WHERE OrderStatus='Success'
ORDER BY OrderCreationDate DESC
LIMIT 3;

mysql rank - row number where field is equal to X

This is my mysql DB:
id, auth, name, points
and what I want to get is to create a rank. So sort all the records by points, and get the number of the row where the auth field is equal to '1'
I were looking for this in stockoverflow archive, in google etc. However, I havn't find what I were looking for. I were trying to do it myself, but none of them didn't work for me.
Could anyone help me, please?
SELECT a.iterator, a.id, a.name, a.points
FROM (
SELECT #rank:=#rank+1 AS iterator, id, name, points, auth
FROM table, (SELECT #rank:=0) tmp
ORDER BY points DESC) a
WHERE a.auth = 1
This should give you the record with rank for the record with auth = 1:
SELECT * FROM
(
SELECT id, auth, name, points, #rownum := #rownum + 1 AS rank
FROM (
SELECT id, auth, name, points
FROM yourTable
ORDER BY points DESC
) a
JOIN (
SELECT #rownum := 0
) r
) b
WHERE b.auth = 1;
sqlfiddle demo

Getting latest rows in MySQL based on date (grouped by another column)

This type of question is asked every now and then. The queries provided works, but it affects performance.
I have tried the JOIN method:
SELECT *
FROM nbk_tabl
INNER JOIN (
SELECT ITEM_NO, MAX(REF_DATE) as LDATE
FROM nbk_tabl
GROUP BY ITEM_NO) nbk2
ON nbk_tabl.REF_DATE = nbk2.LDATE
AND nbk_tabl.ITEM_NO = nbk2.ITEM_NO
And the tuple one (way slower):
SELECT *
FROM nbk_tabl
WHERE REF_DATE IN (
SELECT MAX(REF_DATE)
FROM nbk_tabl
GROUP BY ITEM_NO
)
Is there any other performance friendly way of doing this?
EDIT: To be clear, I'm applying this to a table with thousands of rows.
Yes, there is a faster way.
select *
from nbk_table
order by ref_date desc
limit <n>
Where is the number of rows that you want to return.
Hold on. I see you are trying to do this for a particular item. You might try this:
select *
from nbk_table n
where ref_date = (select max(ref_date) from nbk_table n2 where n.item_no = n2.item_no)
It might optimize better than the "in" version.
Also in MySQL you can use user variables (Suppose nbk_tabl.Item_no<>0):
select *
from (
select nbk_tabl.*,
#i := if(#ITEM_NO = ITEM_NO, #i + 1, 1) as row_num,
#ITEM_NO := ITEM_NO as t_itemNo
from nbk_tabl,(select #i := 0, #ITEM_NO := 0) t
order by Item_no, REF_DATE DESC
) as x where x.row_num = 1;

Rank in MySQL table

I have a MySQL table called "MyTable" and it basically lists usernames and points (two columns, name and points). I want to say something like "what is joe1928's rank?", which of course is based off his points. How could I do this in MySQL without having to download all that data and sort it and determine the rank myself?
The person with the highest number of points would be ranked 1.
Try getting the number of people with a higher score than your user:
select count(*) from MyTable where score > (select score from MyTable where user = 'Joe');
That will return 0 for the top user.
This page seems to describe and solve your problem.
Notes from that page:
SET #rownum := 0;
SELECT rank, correct FROM (
SELECT #rownum := #rownum + 1 AS rank, correct, uid
FROM quiz_user ORDER BY correct DESC
) as result WHERE uid=xxxxxxxx
SELECT #r AS Rank
FROM MyTable u, (SELECT #r := 0)
WHERE (#r := #r + 1) * (u.Username = 'joe1928')
ORDER BY u.Score DESC
LIMIT 1
select * from [TABLENAME] where [USERNAME] = blah order by [POINTS] desc limit 1;
Based on the link posted by #Dave your query will look like something below:
select Rank,name from
(select #rownum:=#rownum+1 AS 'Rank', p.name
from calls p, (select #rownum:=0) r
order by p.points desc) as rankResults
where name = 'joe';
This is from another stack overflow page, seems to solve your problem.
SELECT uo.*,
(
SELECT COUNT(*)
FROM users ui
WHERE (ui.points, ui.id) >= (uo.points, uo.id)
) AS rank
FROM users uo
WHERE id = #id