Using rownum in sub query on oracle 11 - sql

I have query like this.It is working properly on oracle 12.
select * from customers where customerId IN (select custId from Orders where
orderStatus = 'S' and orderCity = 'Amsterdam' and ORDER BY custId DESC FETCH FIRST 10 ROWS ONLY)
But I am using oracle 11.That query is not working on oracle 11.Therefore I changed my query like that
select * from customers where customerId IN (select custId from Orders where
orderStatus = 'S' and orderCity = 'Amsterdam' and ORDER BY custId DESC rownum <= 10)
It gives missing right paranthesis
How can I solve this problem.Do you have any idea?Actually I use a variable instead on 10 number.

Syntax is a bit different - you need an extra subquery so it would need to be more like ...
where customerId IN (select * from (select custId from Orders where orderStatus = 'S' and orderCity = 'Amsterdam' and ORDER BY custId DESC) where rownum <=10)
You wouldn't need the extra subquery if you didn't have the order by clause
For ref see https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns009.htm#:~:text=For%20each%20row%20returned%20by,has%202%2C%20and%20so%20on.

I would phrase this with exists and row_number():
select c.*
from customers
where exists (
select 1
from (
select custId, row_number() over(order by custid desc) rn
from orders
where orderStatus = 'S' and orderCity = 'Amsterdam'
) o
where o.rn <= 10 and o.cusid = c.customerid
)
row_number() ranks orders by descending customer id in the subquery. Then, we filter on the first 10 rows, and use exists to filter the corresponding rows in the outer query.

Related

What is the best query to retrieve the top N highest id from SQL table - The efficent query as possible

Let's say there is a table of customers, each customer in this table has an id which is PK (integer).
What is the most efficient way to write a query that returns the 3rd highest id?
And I in here presume it's 3rd, but my intention is for N highest.
I wrote two queries and I wonder which one is better?
select top 1 Customer_Id
from customers c
where c.Customer_Id not in(
select top 2 cc.Customer_Id
from customers cc
order by cc.Customer_Id desc
)
order by c.Customer_Id desc
------------------------------
select top 1 temp.Customer_Id
from (
select top 3 c.Customer_Id
from customers c
order by c.Customer_Id desc) as temp
order by temp.Customer_Id
If someone here has a better approach, I will be glad to hear.
Just use an OFFSET, like I mentioned:
DECLARE #N int = 3; --Demonstrates that the OFFSET can be parametrised
SELECT CustomerID
FROM dbo.Customer C
ORDER BY CustomerID DESC
OFFSET #N-1 ROWS FETCH NEXT 1 ROWS ONLY;
Something like this using the Row_Number function to list them in order, giving you the ability to select the nth number:
DECLARE #TargetRowNum INT = 2;
WITH CustomerList
AS (
SELECT c.Customer_Id
, CustomerRowNum = ROW_NUMBER()OVER(PARTITION BY c.Customer_Id ORDER BY c.Customer_Id DESC)
FROM customers c
)
SELECT *
FROM CustomerList
WHERE CustomerList.CustomerRowNum = #TargetRowNum;
According to #Larnu, I hope this could be a solution:
select temp2.Customer_Id
from(
select temp.Customer_Id, ROW_NUMBER() over(partition by grp order by temp.Customer_Id desc) as rrank
from (
select c.Customer_Id, 1 as grp
from customers c
) as temp
) as temp2
where temp2.rrank = 3

Firebird how to use IIF in ORDER BY with a subquery's column

The following query doesn't work, because Firebird (2.1) won't recognize the subquery's column.
How can I rewrite it to work?
SELECT I.InvoiceID,
I.PayByDate,
(SELECT FIRST 1 I2.PayByDate
FROM Invoices I2
WHERE I2.OriginalInvoiceID = I.InvoiceID
AND I2.IsDraft < 1
ORDER BY I2.InvoiceID DESC) AS NewPayByDate
FROM Invoices I
WHERE
I.IsDraft < 1
ORDER BY
IIF(NewPayByDate IS NULL,
PayByDate,
NewPayByDate),
I.InvoiceRefNum
Use a subquery:
SELECT InvoiceID, PayByDate, NewPayByDate
FROM (SELECT I.*
(SELECT FIRST 1 I2.PayByDate
FROM Invoices I2
WHERE I2.OriginalInvoiceID = I.InvoiceID AND
I2.IsDraft < 1
ORDER BY I2.InvoiceID DESC
) AS NewPayByDate
FROM Invoices I
WHERE I.IsDraft < 1
) I
ORDER BY IIF(NewPayByDate IS NULL, PayByDate, NewPayByDate),
I.InvoiceRefNum;
I would also recommend using COALESCE() in the ORDER BY:
ORDER BY COALESCE(NewPayByDate, PayByDate),
I.InvoiceRefNum;

Select customer with highest price of all his orders

i want to list customer id with highest sum of price of his orders. Please see graph oí orders down.
SQL DEMO
SELECT *
FROM (
SELECT "customerid", SUM("price")
FROM Orders
GROUP BY "customerid"
ORDER BY SUM("price") DESC
) T
WHERE ROWNUM <= 1
You need to group by customer_id to get all prices of each customers.
Then sum these prices filter it with max( sum(price))or get first row by descending order of sum(price).
--for Oracle
select * from (Select c.name,c.id,sum(o.price) from Customer c
inner join order o on o.customer_id=c.id
group by c.name,c.id
order by sum(o.price)desc
)where rownum =1
--For sql server and mysql
Select top 1 c.name,c.id,sum(o.price) from Customer c
inner join order o on o.customer_id=c.id
group by c.name,c.id
order by sum(o.price)desc

Need to change LIMIT into something else

Is there a way to change "LIMIT 1" and get the same output? I have to get client's name, surname and a quantity of books that has the most books
SELECT stud.skaitytojas.name, stud.skaitytojas.surname,
COUNT (stud.skaitytojas.nr) AS quantity
FROM stud.egzempliorius , stud.skaitytojas
WHERE stud.egzempliorius.client = stud.skaitytojas.nr
GROUP BY stud.skaitytojas.nr
ORDER BY quantity DESC
LIMIT 1
Postgres supports the ANSI standard FETCH FIRST 1 ROW ONLY, so you can do:
SELECT s.name, s.surname, COUNT(s.nr) AS quantity
FROM stud.egzempliorius e JOIN
stud.skaitytojas s
ON e.client = s.nr
GROUP BY s.name, s.surname
ORDER BY quantity DESC
FETCH FIRST 1 ROW ONLY;
Also notice the use of table aliases and proper JOIN syntax. I also prefer to list the columns in the SELECT in the GROUP BY, although that is optional if s.nr is unique.
You can select the row with the highest quantity using row_number()
SELECT * FROM (
SELECT * , row_number() over (order by quantity desc) rn FROM (
SELECT stud.skaitytojas.name, stud.skaitytojas.surname, COUNT (stud.skaitytojas.nr) AS quantity
FROM stud.egzempliorius , stud.skaitytojas
WHERE stud.egzempliorius.client = stud.skaitytojas.nr
GROUP BY stud.skaitytojas.name, stud.skaitytojas.surname
) t
) t where rn = 1
If you want to include ties for the highest quantity, then use rank() instead.

SQL max function with another condition not working

This works perfectly until an order comes in where the stationID is not =2. My logic would be that sql searches where both conditions meet and display those results and not look where timeplaced is max then if stationid does not =2 display nothing which is what its doing.
SELECT OrderNo
FROM Orders
WHERE TimePlaced = (SELECT max(TimePlaced) FROM Orders)
AND StationID=2
Add your condition into the inner select too
SELECT OrderNo
FROM Orders
WHERE TimePlaced =
(
SELECT max(TimePlaced)
FROM Orders
WHERE StationID=2
)
AND StationID=2
But if you do not want to add the condition twice, then just "link" the inner select with the outer:
SELECT OrderNo
FROM Orders O
WHERE TimePlaced =
(
SELECT max(TimePlaced)
FROM Orders
WHERE StationID=O.StationID
)
AND StationID=2
Another way you could try would be with using a CTE and ROW_NUMBER:
;WITH OrdersCTE AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY StationID ORDER BY TimePlaced Desc) AS rn
FROM Orders
)
SELECT *
FROM OrdersCTE
WHERE rn = 1
AND StationID = 2