Get the biggest price using MAX() function - sql

I am using SQL Oracle, and I want to change my query using MAX function and not ROWNUM.
SELECT *
FROM (SELECT a.name, price.price
FROM price
LEFT JOIN a
ON a.id = price.tk_a
ORDER BY price.price DESC)
WHERE ROWNUM <=1;
Any help or suggestions please?

You can use the MAX aggregate function with KEEP ( DENSE_RANK FIRST ORDER BY ... ) to get the maximum of another column:
SELECT MAX( a.name ) KEEP ( DENSE_RANK FIRST ORDER BY p.price DESC ) AS name,
MAX( p.price ) AS price
FROM a
LEFT OUTER JOIN price p
ON ( a.id = p.tk_a );

Try this:
select a1.name, p1.price
from price p1
JOIN a a1 ON a1.id = p1.tk_a
JOIN (SELECT MAX(p.price)
FROM price p) C on p1.price = c.price

MAX and group by
SELECT a.name, MAX(p.price)
FROM price
LEFT JOIN a ON a.id = p.tk_a
GROUP BY a.name
ORDER BY p.price DESC
If you just want the single MAX price then use this
SELECT MAX(p.price), (SELECT MAX(b.name) FROM a b LEFT JOIN price pp ON b.id = pp.tk_a WHERE a.id = b.id AND p.price = pp.price) AS name
FROM price
LEFT JOIN a ON a.id = p.tk_a
ORDER BY p.price DESC

Use This
SELECT *
FROM (SELECT a.name,MAX( price.price)
FROM price
LEFT JOIN a
ON a.id = price.tk_a
GROUP BY a.name
ORDER BY price.price DESC)

Related

Using SQL how can I write a query to find the top 5 per category per month?

I am trying to get the Top 5 rows with the highest number for each category for a specific time interval such as a month. What I currently have returns 5 of the exact same descriptions for a category. I am trying to get the top five. This only happens when I try to sort it based on a time period.
WITH CustomerRank
AS
(SELECT
Count(*) AS "Count",
d.Item,
d.Description,
Name,
i.Type,
d.CreatedOn
FROM [dbo].i,
d,
dbo.b,
as,
a,
c
WHERE d.Inspection_Id = i.Id AND d.Inspection_Id = i.Id AND
b.Id = i.BuildingPart_Id AND b.as= Assessments.Id
AND as.Application_Id = a.Id AND a.Customer_Id = Customers.Id
group by d.Item, d.Description, Name, i.Type, d.CreatedOn
)
select * from (
SELECT "Count",Item,Description,Type,ROW_NUMBER() Over (PARTITION BY Name order by "Count" desc) AS RowNum, Name, CreatedOn
FROM CustomerRank
where CreatedOn > '2017-1-1 00:00:00'
) s where RowNum <6
Cheers
Try something like this:
WITH CustomerRank
AS
(SELECT
Count(*) AS "Count",
d.Item, d.Description, Name, i.Type
FROM dbo.Inspection i
INNER JOIN dbo.Details d ON d.Inspection_Id = i.Id
INNER JOIN dbo.BuildingParts b ON b.Id = i.BuildingPart_Id
INNER JOIN dbo.Assessments a ON a.Id = b.AssessmentId
INNER JOIN dbo.Applications ap ON ap.Id = a.Application_Id
INNER JOIN dbo.Customers c ON c.Id = a.Customer_Id
where CreatedOn > '2017-1-1 00:00:00'
group by d.Item, d.Description, Name, i.Type
)
select * from (
SELECT "Count",Item,Description,Type,ROW_NUMBER() Over (PARTITION BY Name order by "Count" desc) AS RowNum, Name
FROM CustomerRank
) s where RowNum <6
The idea is that the CreatedOn column must be removed from the GROUP BY clause (because if you keep it there, we would get a different row for each value of the CreatedOn column).
Also, it's better to use JOIN-s and aliases for each table.

How to make LEFT JOIN with row having max date?

I have two tables in Oracle DB
Person (
id
)
Bill (
id,
date,
amount,
person_id
)
I need to get person and amount from last bill if exist.
I trying to do it this way
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN Bill b
ON b.person_id = p.id AND b.date = (SELECT MAX(date) FROM Bill WHERE person_id = 1)
WHERE p.id = 1;
But this query works only with INNER JOIN. In case of LEFT JOIN it throws ORA-01799 a column may not be outer-joined to a subquery
How can I get amoun from the last bill using left join?
Please try the below avoiding sub query to be outer joined
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN(select * from Bill where date =
(SELECT MAX(date) FROM Bill b1 WHERE person_id = 1)) b ON b.person_id = p.id
WHERE p.id = 1;
What you are looking for is a way to tell in bills, for each person, what is the latest record, and that one is the one to join with. One way is to use row_number:
select * from person p
left join (select b.*,
row_number() over (partition by person_id order by date desc) as seq_num
from bills b) b
on p.id = b.person_id
and seq_num = 1
You cannot have a subquery inside an ON statement.
Instead you need to convert your LEFT JOIN statement into a whole subquery.
Not tested but this should work.
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN (
SELECT id FROM Bill
WHERE person_id = p.id
AND date = (SELECT date FROM Bill WHERE person_id = 1)) b
WHERE p.id = 1;
I'm not quite sure why you would want to filter for the date though.
Simply filtering for the person_id should do the trick
you should join Person and Bill to the result for max date in bill related to person_id
select Person.id, bill.amount
from Person
left join bill on bill.person_id = person.id
left join (
select person_id, max(date) as max_date
from bill
group by person_id ) t on t.person_id = Person.id and b.date = t.max_date
Hey you can do like this
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN Bill b
ON b.person_id = p.id AND b.date = (SELECT max(date) FROM Bill WHERE person_id = 1)
WHERE p.id = 1
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN Bill b
ON b.person_id = p.id
WHERE (SELECT max(date) FROM bill AS sb WHERE sb.person_id=p.id LIMIT 1)=b.date;
SELECT
p.id,
c.amount
FROM Person p
LEFT JOIN (select b.person_id as personid,b.amount as amount from Bill b where b.date1= (select max(date1) from Bill where person_id=1)) c
ON c.personid = p.id
WHERE p.id = 1;
try this
select * from person p
left join (select MAX(id) KEEP (DENSE_RANK FIRST ORDER BY date DESC)
from bills b) b
on p.id = b.person_id
I use GREATEST() function in join condition:
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN Bill b
ON b.person_id = p.id
AND b.date = GREATEST(b.date)
WHERE p.id = 1
This allows you to grab the whole row if necessary and grab the top x rows
SELECT p.id
,b.amount
FROM person p
LEFT JOIN
(
SELECT * FROM
(
SELECT date
,ROW_NUMBER() OVER (PARTITION BY person_id ORDER BY date DESC) AS row_num
FROM bill
)
WHERE row_num = 1
) b ON p.id = b.person_id
WHERE p.id = 1
;

SQL MAX of SUM without sub-querying

I'm trying to execute a SQL query which requires grouping by MAX of SUM calculation (in PostgreSQL).
I found here some solutions which uses sub-querying but I need the solution without it (if it's possible).
Query:
SELECT "Festival".title,
"Musician".aname,
SUM("Musician".salary * "Musician".percentage / 100) AS "agent_total_profit"
FROM "Festival"
INNER JOIN "Booked"
ON "Booked".title = "Festival".title
INNER JOIN "Musician"
ON "Musician".id = "Booked".id
GROUP BY "Festival".title,
"Musician".aname
ORDER BY "Festival".title
Result:
the result is not as expected, I want to find for each festival title, the musician aname with the max agent_total_profit.
Desired result:
Thanks in advance.
Use DISTINCT ON:
SELECT DISTINCT ON (f.title) f.title, m.aname,
SUM(m.salary * m.percentage / 100) AS "agent_total_profit"
FROM "Festival" f INNER JOIN
"Booked" b
ON b.title = f.title INNER JOIN
"Musician" m
ON m.id = b.id
GROUP BY f.title, m.aname
ORDER BY f.title, "agent_total_profit" DESC;
The more traditional SQL method uses row_number():
SELECT f.*
FROM (SELECT f.title, m.aname,
SUM(m.salary * m.percentage / 100) AS "agent_total_profit",
ROW_NUMBER() OVER (PARTITION BY f.title ORDER BY SUM(m.salary * m.percentage / 100) DESC) as seqnum
FROM "Festival" f INNER JOIN
"Booked" b
ON b.title = f.title INNER JOIN
"Musician" m
ON m.id = b.id
GROUP BY f.title, m.aname
) f
WHERE seqnum = 1;
ORDER BY f.title, "agent_total_profit" DESC;

product code repeat in query

I have this tables
Product
IDProd || Name
Time_Price
IDPrice || IDProd || Price || Time
the query is:
SELECT P.IDProd,P.Name,TP.Price,MAX(TP.Time)
FROM Product P INNER JOIN Time_Price TP ON P.IDProd=TP.IDProd
GROUP BY P.IDProd,P.Name,TP.Price
I need that the product code does not repeat
This will give you the latest Price for every product.
SELECT IDProd, Name,
IDPrice, Price, Time
FROM
(
SELECT a.IDProd, a.Name,
b.IDPrice, b.Price, b.Time,
ROW_NUMBER() OVER (PARTITION BY a.IDProd ORDER BY b.Time DESC) rn
FROM Product a
INNER JOIN Time_price b
ON a.IDProd = b.IDProd
) a
WHERE a.rn = 1
without using window function,
SELECT a.IDProd, a.Name,
b.IDPrice, b.Price, b.Time
FROM Product a
INNER JOIN Time_price b
ON a.IDProd = b.IDProd
INNER JOIN
(
SELECT IDProd, MAX(Time) Time
FROM Time_price
GROUP BY IDProd
) c ON b.IDProd = c.IDProd AND
b.Time = c.Time

T-SQL get max value

I have the following query
SELECT P.ID, MAX(ENTERDATE) as ENTERDATE, MAX(B.CostID) as CostID
FROM Protocol P JOIN BANK B ON P.ID= B.ID
group by P.ID
I need to find out what the Maximum enterdate was along with the corresponding CostID but I do not want to use MAX(B.CostID) but I am forced
to do so as I have a group by P.ID and all other fields need to have some kind of aggregate. How do I say group by P.ID and show me the max(enterdate) but give me the corresponding CostID for that Enterdate?
SELECT P.ID,
ENTERDATE = MAX(p.ENTERDATE),
CostID = (SELECT CostID FROM Bank WHERE ID = p.ID)
FROM Protocol P
group by P.ID
OR something like
SELECT t.*,
CostID
FROM Bank b
JOIN (
SELECT P.ID,
ENTERDATE = MAX(p.ENTERDATE)
FROM Protocol P
group by P.ID
) t ON t.ID = b.ID
Why not subquery it:
SELECT MaxTable.*, BANK.CostID AS CostID
FROM
(
SELECT P.ID, MAX(ENTERDATE) AS ENTERDATE
FROM Protocol P
GROUP BY P.ID
) AS MaxTable
JOIN BANK
ON MaxTable.ID = BANK.ID
You can try with the analytical function ROW_NUMBER:
SELECT *
FROM
(SELECT p.id, p.enterdate, b.costid,
ROW_NUMBER() OVER(PARTITION BY p.id ORDER BY p.enterdate DESC) AS rownum
FROM Protocol P JOIN BANK B ON P.ID= B.ID)
WHERE rownum = 1