product code repeat in query - sql

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

Related

SQL / Redshift Error - Filtering only first occurence of a value

I am trying to return the first occurence of a value using the below SQL script:
SELECT a.store_id, b.store_name, c.prod_id FROM
(
select a.store_id as sh, b.store_name, c.prod_id
count(1) ct,row_number() over (partition by store_id order by store_id
desc) row_num
from stores a, store_details b , product c
where a.id=b.store_id and a.prod_id = c.id and b.id = 101
group by a.store_id as sh, b.store_name, c.prod_id,
)t
WHERE row_num = 1;
I get an error
Invalid operation : relation "a" does not exist.
I am using a Redshift DB. Could anyone assist on this. Thanks..
You are selecting from a subquery, and the alias for it is "T", you cannot reference subquery alias from outside the subquery.
SELECT t.store_id, T.store_name, T.prod_id
FROM
(
select a.store_id as sh, b.store_name, c.prod_id
count(1) ct,row_number() over (partition by store_id order by store_id
desc) row_num
from stores a, store_details b , product c
where a.id=b.store_id and a.prod_id = c.id and b.id = 101
group by a.store_id as sh, b.store_name, c.prod_id,
)T
WHERE t.row_num = 1;

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
;

DB2 - Invalid use of an aggregate function SQLCODE=-120

Can anyone help me to understand what is wrong with this Db2 query syntax,it is failing with SQLCODE -120 because i am trying to use row_number()?
SELECT COUNT(ORDER_ID) OVER() TOTAL_NO_OF_RECORDS,
ROW_NUMBER() OVER (ORDER BY CREATED_DATE DESC) AS ROW_NUM
FROM (
SELECT DISTINCT A.ORDER_ID ORDER_ID,
B.AgencyName AS AGENCY_NAME,
C.FirstName FIRST_NAME,
C.LastName LAST_NAME,
DEMOGRAPHIC.State STATE,
A.CreatedTS CREATED_DATE,
E.WritingTIN WRITING_TIN,
E.ParentTIN PARENT_TIN
FROM DBO.TABLE1 A
INNER JOIN
DBO.TABLE2 TABLE2 ON TABLE2.ORDER_ID=A.ORDER_ID
INNER JOIN
DBO.TABLE3 TABLE3 ON TABLE3.QuoteId=TABLE2.QuoteId
INNER JOIN
DBO.Demographic DEMOGRAPHIC ON
DEMOGRAPHIC.DemographicId=TABLE3 .DemographicId
INNER JOIN
DBO.Agent E ON E.AgentId=DEMOGRAPHIC.AgentId
INNER JOIN
DBO.User USER ON USER.WebAcctID=AGENT.WebAcctId
INNER JOIN
DBO.Shopper SHOPPER ON SHOPPER.ShopperId=DEMOGRAPHIC.ShopperId
LEFT OUTER JOIN
DBO.Subsidy D ON D.demographicId=DEMOGRAPHIC.demographicId
LEFT OUTER JOIN
DBO.Employer EMPLOYER ON DEMOGRAPHIC.demographicId=EMPLOYER.demographicId
WHERE E.WritingTIN = 'XYZ' AND E.ParentTIN = 'XYZ'
AND DEMOGRAPHIC.State='OH'
AND A.Status IN ('X','Y','Z')
)AS ORDER_DETAILS
where ROW_NUMBER() OVER (ORDER BY CREATED_DATE DESC) BETWEEN ((1*50)-50)+1 AND 1*50 ORDER BY CREATED_DATE DESC
ERROR SHOWN:Invalid use of an aggregate function or OLAP function.. SQLCODE=-120, SQLSTATE=42903, DRIVER=4.18.60
You have multiple errors:
X is not defined in the subquery.
B.CREATED_DATE is referenced in the outer query, but it is not defined.
ROW_NUMBER() is used in the WHERE clause.
This would seem to be the intention of the query you write:
SELECT COUNT(*) OVER () NO_OF_RECORDS, ROW_NUM
FROM (SELECT A.ID, B.FirstName as FIRST_NAME, B.LastName as LAST_NAME,
MAX(B.CREATED_DATE) as CREATED_DATE,
ROW_NUMBER() OVER (ORDER BY MAX(CREATED_DATE) DESC) AS ROW_NUM
FROM SCHEMANAME.A A INNER JOIN
SCHEMANAME.B B
ON B.ShopperId = A.ShopperId LEFT OUTER JOIN
SCHEMANAME.C C
ON C.demographicId = B.demographicId
WHERE A.WritingTIN = 'XYZ' AND A.ParentTIN = 'XYZ' AND
B.State = 'OH' AND C.Status IN ('X', 'Y', 'Z')
GROUP BY A.ID, B.FirstName, B.LastName
) ORDER_DETAILS
WHERE ROW_NUM BETWEEN ((1*50)-50)+1 AND 1*50
ORDER BY CREATED_DATE DESC;
I'm not sure that this result makes sense, but it should fix your error.

Get the biggest price using MAX() function

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)