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;
Related
Create two tables emp_merits (meritid, empid, date, meritpoints),emp1(empid,empname) Each employee will be given merit points every month based on their performance. So same employee can have multiple entries in the table with different meritpoints.
List all the merits received by a specific employee (empid will be input here) between specific dates
Rank each employee based on their merit points from highest to lowest
so far i have tried this query
select empid , sum (meritpoints) as totalmerits , (DENSE_RANK()OVER (PARTITION BY empid ORDER BY meritpoints desc)) AS rank from emp_merit
group by empid,meritpoints
order by empid ,totalmerits desc
You could try this:
SELECT #rownum := #rownum + 1 AS rank, a.*
FROM (
SELECT empid, sum(meritpoints) AS totalmerits
FROM emp_merits
GROUP BY empid
ORDER BY totalmerits) a, (SELECT #rownum := 0) r ;
you probably need your specific dates in the WHERE-clause.
You can implement dense_rank() using variables:
select empid, totalmerits,
(#rn := if(#m = totalmerits, #rn,
if(#m := totalmerits, #rn + 1, #rn + 1)
)
) as rank
from (select empid, sum(meritpoints) as totalmerits
from emp_merit
group by empid
order by totalmerits desc
) e cross join
(select #m := -1, #rn := 0) params;
Let's say there are millions of records in my_table.
Here is my query to extract rows with a specific name from list:
SELECT * FROM my_table WHERE Name IN ('name1','name2','name3','name4')
How do I limit the returned result per name1, name2, etc?
The following query would limit the whole result (to 100).
SELECT * FROM my_table WHERE Name IN ('name1','name2','name3','name4') LIMIT 100
I need to limit to 100 for each name.
This is a bit of a pain in MySQL, but the best method is probably variables:
select t.*
from (select t.*,
(#rn := if(#n = name, #rn + 1,
if(#n := name, 1, 1)
)
) as rn
from my_table t cross join
(select #n := '', #rn := 0) params
order by name
) t
where rn <= 100;
If you want to limit this to a subset of the names, then add the where clause to the subquery.
Note: If you want to pick certain rows -- such as the oldest or newest or biggest or tallest -- just add a second key to the order by in the subquery.
Try
SELECT * FROM my_table WHERE Name IN ('name1','name2','name3','name4') FETCH FIRST 100 ROWS ONLY
Suppose that I have a database which contains the following columns:
VehicleID|timestamp|lat|lon|
I may have multiple times the same VehicleId but with a different timestamp. Thus VehicleId,Timestamp is the primary key.
Now I would like to have as a result the last N measurements per VehicleId or the first N measurements per vehicleId.
How I am able to list the last N tuples according to an ordering column (e.g. in our case timestamp) per VehicleId?
Example:
|VehicleId|Timestamp|
1|1
1|2
1|3
2|1
2|2
2|3
5|5
5|6
5|7
In MySQL, this is most easily done using variables:
select t.*
from (select t.*,
(#rn := if(#v = vehicle, #rn + 1,
if(#v := vehicle, 1, 1)
)
) as rn
from table t cross join
(select #v := -1, #rn := 0) params
order by VehicleId, timestamp desc
) t
where rn <= 3;
I have the table with data:
And for this table I need to create pegination by productId column. I know about LIMIT N,M, but it works with rows and not with groups. For examle for my table with pegination = 2 I expect to retrieve all 9 records with productId = 1 and 2 (the number of groups is 2).
So how to create pegination by numbers of groups ?
I will be very thankfull for answers with example.
One way to do pagination by groups is to assign a product sequence to the query. Using variables, this requires a subquery:
select t.*
from (select t.*,
(#rn := if(#p = productid, #rn + 1,
if(#rn := productid, 1, 1)
)
) as rn
from table t cross join
(select #rn := 0, #p := -1) vars
order by t.productid
) t
where rn between X and Y;
With an index on t(productid), you can also do this with a subquery. The condition can then go in a having clause:
select t.*,
(select count(distinct productid)
from t t2
where t2.productid <= t.productid)
) as pno
from t
having pno between X and Y;
Try this:
select * from
(select * from <your table> where <your condition> group by <with your group>)
LIMIT number;
I am using this code to rank users:
SELECT #rn:=#rn+1 AS rank, userid, amount
FROM (
SELECT userid, sum(amount) AS amount
FROM leads WHERE date(time)='2013-09-15'
GROUP BY userid
ORDER BY amount DESC
) t1 , (SELECT #rn:=0) t2;
The result is like this:
rank userid amount
1 11 1.15
2 10 1.15
It keeps adding rank even if the user has the same amount, any ideas how to fix this? Yes, I have searched google and here on stackoverflow, but I have not been able to fix this problem.
First, you don't need a subquery to do what you want.
The following does a dense ranking of the amounts, by introducing another variable to remember the total amount:
SELECT userid, sum(amount) AS amount,
if(#amount = amount, #rn, #rn := #rn + 1) as ranking,
#amount := amount
FROM leads cross join
(select #rn := 0, #amount := -1) const
WHERE date(time) = '2013-09-15'
GROUP BY userid
ORDER BY amount DESC;