Print all details of the 16th order placed by each customer if any.
How to print exact 16th Order?
SELECT COUNT(orderId)
FROM orders
GROUP BY CustomerID
ORDER BY CustomerID;
We can use a CTE and RANK to create a list of all orderId's, customerID's and their "order" as you named it.
Then we fetch those entries from the entire result whose order is 16.
WITH result AS
(
SELECT orderId, customerID,
RANK() OVER
(PARTITION BY customerID
ORDER BY orderId) AS rnk
FROM orders
)
SELECT orderId, customerID
FROM result
WHERE rnk=16
GROUP BY orderId, customerID
ORDER BY customerID;
For customerID's having less than 16 orders, nothing will be selected.
We can also use ROW_NUMBER instead of RANK in the above query, this makes no difference in your use case.
Select * from
(
SELECT *,
DENSE_RANK()
OVER(
PARTITION BY customerID
ORDER BY orderID
) my_rank
FROM orders
) as myTable
where my_rank = 16
order by CustomerID;
You can just use offset like:
SELECT *
FROM orders
GROUP BY CustomerID
ORDER BY CustomerID
LIMIT 1 OFFSET 15;
and set the OFFSET value to 15 so it skips the first 15 values and prints from the 16th value and limit it to only one row by setting the LIMIT value to 1
Related
I'm trying to improve my query for this topic at hand. I'm trying to find the top 5 and bottom 5 growth rates per state from 2020 to 2021 in my org. The table has the columns as specified: orderid, orderdate, totaldue, state, etc. (these are probably the most important columns). This is the query I created so far, while it works I think it would be more efficient if I was able to implement a window function instead.
SELECT state, SUM(TotalDue) as sum
into #temp2020
from table
where OrderDate like "2020%"
group by StateProvince
order by sum desc;
SELECT state, SUM(TotalDue) as sum
into #temp2021
from table
where OrderDate like "2021%"
group by StateProvince
order by sum desc;
--top 5 growth rates--
select #temp2020.state, ((#temp2021.sum-#temp2020.sum)/#temp2020.sum) as 'growthrate'
from #temp2020
join #temp2021 on #temp2021.state = #temp2020.state
order by growthrate desc limit 5
--bottom 5 growth rates--
select #temp2020.state, ((#temp2021.sum-#temp2020.sum)/#temp2020.sum) as 'growthrate'
from #temp2020
join #temp2021 on #temp2021.state = #temp2020.state
order by growthrate asc limit 5
drop table if exists #temp2020
drop table if exists #temp2021
You could use DENSE_RANK here:
WITH cte AS (
SELECT state, SUM(TotalDue) AS sum,
DENSE_RANK() OVER (ORDER BY SUM(TotalDue)) rnk_asc,
DENSE_RANK() OVER (ORDER BY SUM(TotalDue) DESC) rnk_desc
FROM yourTable
WHERE YEAR(OrderDate) IN (2020, 2021)
GROUP BY state
)
SELECT state, sum
FROM cte
WHERE rnk_asc <= 5 OR rnk_desc <= 5
ORDER BY state, sum;
I have this table
i want to ignore productNo and sum all product count accordingly.
select sum(count), max(productNo)
from Table
where date between 117 and 118
group by product
this one gives wrong result...
I want to have sum of counts for each Product-ProductNo combination
try like below
select product,productno,sum(count) as result
from table_name
where productno='X1'
group by product,productno
seems you need the firts rows order by result
select product,productno,sum(count) as result
from table
group by product,productno
order by result
limit 1
Since you haven't tagged any DBMS so, i would use row_number():
select t.*
from (select product, productno, sum(count) as cnt,
row_number() over (partition by product order by sum(count) desc) as seq
from table t
group by product, productno
) t
where seq = 1;
You can also use LIMIT clause (but not for each product) :
select product, productno, sum(count) as cnt
from table t
group by product, productno
order by cnt desc
limit 1;
Some other DBMS requires TOP clause instead of LIMIT clause so, you can change accordingly but the idea would be same.
select sum(count), max(productNo)
from Table
where date between 117 and 118
group by product, productNo
with this it works :)
I am trying to write a query to find the 2nd oldest girl student in a class
DOB is date of birth as time stamp
name and gender are varchar
SELECT min(DOB)
FROM Student
WHERE DOB > (SELECT min(DOB) FROM Student where gender='girl')
Is this correct?
Or simpler:
SELECT DOB
FROM Student
WHERE gender='girl'
GROUP BY DOB
ORDER BY DOB ASC
LIMIT 1,1
Grouping by DOB means that two identical DOBs (twins?) that the next lowest is select. It can be omitted in a second identical date counts as the second oldest.
The below query will provide you the desired output
WITH T AS
(
SELECT *
DENSE_RANK() OVER (ORDER BY DOB ) AS Rnk
FROM Student
WHERE gender='girl'
)
SELECT min(DOB)
FROM T
WHERE Rnk = 2;
You can change the RNK value to get the next oldest value, say for third oldest you can use WHERE Rnk = 3
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY Student.DOB)) as row,*
FROM Student )
SELECT * FROM myTableWithRows WHERE row = 2
I created this fake example and the query result is the following:
Or alternatively you can use this query:
Select top 1 * from (select top 2 from Student order by dob desc) order by dob desc
Write a query to display the customer name who visited the second highest number of times
select customer_id,count(*) from booking group by customer_id ;
using this query i got the count of number of visits for each customer as shown below
CUSTOMER_ID,COUNT(*)
C001,6
C002,1
C003,1
C004,1
C005,4
but i want to display only c005 since he has visited the second maximum time
SELECT customer_id, COUNT(*)
FROM booking
GROUP BY customer_id
HAVING COUNT(*) <> (SELECT MAX(t.custCount)
FROM (SELECT COUNT(*) AS custCount
FROM booking
GROUP BY customer_id) t )
ORDER BY COUNT(*) DESC
LIMIT 1
As a side note, this won't work if there are ties for second place. In this case, you use the above query as a condition in the WHERE clause, e.g.
SELECT customer_id
FROM booking
GROUP BY customer_id
HAVING COUNT(*) = (query given above)
You can use a outer query and filter the same like
select customer_id from (
select customer_id,
count(*) as datacount
from booking
group by customer_id ) xxx
order by datacount desc
limit 1;
From the following four records, I want to select the OwnerId of second-latest record
ItemId OwnerId Date
11477 20981 2013-05-13
11477 1 2013-05-21
11477 21086 2013-05-22 #this is the one I'm talking about
11477 3868 2013-05-24
How to go about it?
This needs ItemID to be specified,
SELECT *
FROM TableName
WHERE ItemID = '11477'
ORDER BY DATE DESC
LIMIT 1,1
SQLFiddle Demo
However, if you don't want to specify the ItemID, and you want to get all second latest record for every ItemID, you can use a correlated subquery to generate a sequence number for every ItemID based on lastest DATE,
SELECT ItemId, OwnerID, Date
FROM
(
SELECT A.ItemId,
A.OwnerId,
A.Date,
(
SELECT COUNT(*)
FROM tableName c
WHERE c.ItemId = a.ItemId AND
c.Date >= a.Date) AS RowNumber
FROM TableName a
) x
WHERE RowNumber = 2
SQLFiddle Demo
select ownerid
from your_table
order by date desc
limit 1, 1
I think you can just to ORDER BY date descending, which will give you an order from newer to older, then LIMIT 1,1 to get only the second result, which should be the one you look for
SELECT *
FROM table
ORDER BY date DESC
LIMIT 1,1