Sql Query for Identified by duplicates and remove in it - sql

SELECT i.product_id, o.date_added
FROM ims_order_product i
INNER JOIN ims_order o
WHERE i.product_id IN (SELECT p.product_Id FROM ims_product p)
The Query Return Product_id column and Date column But Product_id column contain duplicates So I want remove duplicates in Product_id based on Date_added by recent Date Can any give the answer.

Try grouping by product_id. Below query will select the latest date for duplicate product_id
SELECT i.product_id, MAX(o.date_added) FROM ims_order_product i INNER JOIN ims_order o WHERE i.product_id IN (SELECT p.product_Id FROM ims_product p) GROUP BY i.product_id

Please try this query
SELECT i.product_id, MAX(o.date_added) date_added
FROM ims_order_product i
INNER JOIN ims_order o --add your join condition here
WHERE EXISTS (SELECT p.product_Id FROM ims_product p WHERE p.product_Id = i.product_id)
GROUP BY i.product_id

SELECT * FROM (SELECT i.product_id, o.date_added, o.order_id FROM ims_order_product i
JOIN ims_order o ON o.order_id = i.order_id
JOIN ims_product pr ON pr.product_id = i.product_id ORDER BY date_added DESC) AS sub GROUP BY product_id

Related

How to select everything from one table and a row from another table in SQL

I want to select everything from the table PRODUCT_INFORMATION. I tried to use p.* and PRODUCT_INFORMATION.* but it's not working? Where is my mistake? Is it something with JOIN?
SELECT
p.PRODUCT_NAME ,
SUM (oi.QUANTITY) TOTAL_QUANTITY,
o.ORDER_MODE
FROM PRODUCT_INFORMATION p
LEFT JOIN ORDER_ITEMS oi ON p.PRODUCT_ID = oi.PRODUCT_ID
LEFT JOIN ORDERS o ON o.ORDER_ID = oi.ORDER_ID
WHERE INSTR (p.PRODUCT_NAME, '<') = 0
AND INSTR (p.PRODUCT_NAME, '_') = 0
GROUP BY p.PRODUCT_NAME, p.WARRANTY_PERIOD, o.ORDER_MODE
HAVING SUM (oi.QUANTITY) > 200
ORDER BY p.WARRANTY_PERIOD;
In MySQL, you can aggregate by the primary key of a table and still accept all the columns. Assuming that PRODUCT_ID is the primary key, you can use:
SELECT p.*, SUM(oi.QUANTITY) as TOTAL_QUANTITY, o.ORDER_MODE
FROM PRODUCT_INFORMATION p LEFT JOIN
ORDER_ITEMS oi
ON p.PRODUCT_ID = oi.PRODUCT_ID LEFT JOIN
ORDERS o
ON o.ORDER_ID = oi.ORDER_ID
WHERE INSTR (p.PRODUCT_NAME, '<') = 0 AND
INSTR (p.PRODUCT_NAME, '_') = 0
GROUP BY p.PRODUCT_ID, o.ORDER_MODE
HAVING SUM (oi.QUANTITY) > 200
ORDER BY p.WARRANTY_PERIOD;

How to add TOP 1 in query with left join in views?

I have 3 same product in ID=42, with 3 different images. I want to take the first image from the product ID, I try adding "TOP 1", error
This is my query
CREATE OR REPLACE VIEW UserOrdersView
AS
SELECT
u.[User_ID],
p.Product_Name,
p.Price,
o.Order_Price,
o.Order_ID,
i.[Image]
FROM Product p
LEFT JOIN Orders o ON o.Product_ID = p.Product_ID
INNER JOIN Users u ON u.[User_ID]= o.[User_ID]
LEFT JOIN Product_Images i ON i.Product_ID = p.Product_ID
WHERE o.[User_ID] = 42
You need to use OUTER APPLY to get top 1 image data from Product_image table based on Product ID.
Please check this Real life example, when to use OUTER / CROSS APPLY in SQL stackoverflow link for more knowledge.
Please check below updated view code for your answer.
CREATE OR REPLACE VIEW UserOrdersView
AS
BEGIN
SELECT
u.[User_ID],
p.Product_Name,
p.Price,
o.Order_Price,
o.Order_ID,
i.[Image]
FROM Product p
INNER JOIN Users u ON u.[User_ID]= o.[User_ID]
LEFT JOIN Orders o ON o.Product_ID = p.Product_ID
OUTER APPLY
(
SELECT TOP 1
T2.[Image]
FROM Product_Images T2
WHERE T2.Product_ID = p.Product_ID
) i
WHERE o.[User_ID] = 42
END
GO
WITH cte as (
SELECT
u.[User_ID],
p.Product_Name,
p.Price,
o.Order_Price,
o.Order_ID,
i.[Image],
ROW_NUMBER() OVER (PARTITION BY i.[Image] ORDER BY p.Product_Name) AS rn
FROM Product p
LEFT JOIN Orders o ON o.Product_ID = p.Product_ID
INNER JOIN Users u ON u.[User_ID]= o.[User_ID]
LEFT JOIN Product_Images i ON i.Product_ID = p.Product_ID
)
SELECT [User_ID],Product_Name,Price,Order_Price,Order_ID,[Image] FROM cte
WHERE rn=1
Put your all query inside a CTE with a new column that you will use to filter the results.
This new column is produced with ROW_NUMBER() function partitioned by Product_Name

How to select distinct items without having to use in group by clause?

I am trying to find sum of some columns using SQL like this:
select distinct c.customer,
c.customer_id,
sum(d.delay) as delay,
sum(d.delayed_amount) as delay_amt,
pd.product
from product pd
inner join mfg_company mfg on pd.product_id=mfg.product_id
inner join store s on mfg.store_id = s.store_id
inner join customer c on s.customer = c.customer_id
join delay_detail d on pd.product_id = d.material
where d.product_mfg_id = 466
group by c.customer,customer_id
order by c.customer,c.customer_id
The problem is mfg_company has duplicate product_id's(multiple mappings) ,So when I am trying to find the sum it's including those duplicates too.
Using product_id in group by clause doesn't help the result I want to see.So how to join only on distinct product_id's?
You can try below query if this helps -
select distinct c.customer
,c.customer_id
,sum(d.delay) as delay
,sum(d.delayed_amount) as delay_amt
,pd.product
from product pd
inner join (select distinct product_id
,store_id
from mfg_company) mfg on pd.product_id=mfg.product_id
inner join store s on mfg.store_id = s.store_id
inner join customer c on s.customer = c.customer_id
join delay_detail d on pd.product_id = d.material
where d.product_mfg_id = 466
group by c.customer,customer_id
order by c.customer,c.customer_id
I think the solution to your problem is to pre-aggregate the delays. It is entirely unclear if you want the product in the result set. Assuming you do not:
select c.customer, c.customer_id,
sum(d.delay) as delay, sum(d.delay_amt) as delay_amt
from product pd join
mfg_company mfg
on pd.product_id = mfg.product_id join
store s
on mfg.store_id = s.store_id
customer c
on s.customer = c.customer_id join
(select d.material, sum(d.delay) as delay, sum(d.delayed_amount) as delay_amt
from delay_detail d
group by d.material
) d
on pd.product_id = d.material
where d.product_mfg_id = 466
group by c.customer, customer_id
order by c.customer, c.customer_id;
Note that using select distinct with group by is almost never needed.

Need to optimize query to use in an indexed view

I have this query in a view that I cannot index because of the referenced table t. I've converted to a sub-query which doesn't work either and is a smidgen slower anyway.
I simply need the last price a productid was sold for.
SELECT op.productId, op.Price, o.createdat
from (
SELECT max(op.OrderProductid), MAX(o.OrderId)
FROM dbo.OrderProduct op
INNER JOIN dbo.Order so ON op.OrderId = so.OrderId
WHERE o.StatusId IN (1,2,3)
GROUP BY op.ProductId
) t
join OrderProduct op on op.Productid = t.Productid
join Order o ON o.OrderId = op.OrderId
Considering your last statement:
I simply need the last price a productid was sold for.
You can use row_number for this:
select *
from (
select op.productid, op.price, o.createdat,
row_number() over (partition by op.productid order by o.orderid desc) rn
from orderproduct op
join order o on op.orderid = o.orderid
) t
where rn = 1

Missing Right Parenthesis issue

This is the Query I have written
Select C.CUST_NAME,P.PROD_DESCRIP from Customer C
JOIN (Ord O,OrderItem OT, Product P) ON (C.CUST_ID = O.CUST_ID AND O.ORD_ID = OT.ORD_ID AND OT.PROD_ID = P.PROD_ID) GROUP BY C.CUST_NAME ORDER BY OT.ORDITEM_QTY DESC
But the issue is it giving me Right Parenthesis Missing issue
Although that join syntax is allowed in some databases, it is really much clearer to split out the joins:
Select C.CUST_NAME, P.PROD_DESCRIP
from Customer C JOIN
Ord O
on C.CUST_ID = O.CUST_ID JOIN
OrderItem OT
on O.ORD_ID = OT.ORD_ID JOIN
Product P
ON OT.PROD_ID = P.PROD_ID
GROUP BY C.CUST_NAME
ORDER BY OT.ORDITEM_QTY DESC;
By the way, this probably isn't doing what you think it does. It is returning a customer name along with an arbitrary prod_descrip. It is then ordering this result by an arbitrary quantity -- perhaps from the same or a different row.
If you want to get the customer name along with the product with the maximum quantity for that customer, you can do this:
Select C.CUST_NAME,
substring_index(group_concat(P.PROD_DESCRIP order by OT.ORDITEM_QTY desc), ',', 1) as PROD_DESCRIP
from Customer C JOIN
Ord O
on C.CUST_ID = O.CUST_ID JOIN
OrderItem OT
on O.ORD_ID = OT.ORD_ID JOIN
Product P
ON OT.PROD_ID = P.PROD_ID
GROUP BY C.CUST_NAME;
Note: If PROD_DESCRIP could have a comma then you will want to use a different separator character.
EDIT:
The above is the MySQL solution. In Oracle, you would do:
select CUST_NAME, PROD_DESCRIP
from (Select C.CUST_NAME, P.PROD_DESCRIP,
row_number() over (partition by C.CUST_NAME order by OT.ORDITEM_QTY desc) as seqnum
from Customer C JOIN
Ord O
on C.CUST_ID = O.CUST_ID JOIN
OrderItem OT
on O.ORD_ID = OT.ORD_ID JOIN
Product P
ON OT.PROD_ID = P.PROD_ID
) t
where seqnum = 1;
This is actually the preferred standard SQL solution. It will work in most databases (SQL Server, Oracle, Postgres, DB2, and Teradata).
SELECT C.CUST_NAME, P.PROD_DESCRIP
FROM Customer C
INNER JOIN Ord O ON C.CUST_ID = O.CUST_ID
INNER JOIN OrderItem OT ON O.ORD_ID = OT.ORD_ID
INNER JOIN Product P ON OT.PROD_ID = P.PROD_ID
GROUP BY C.CUST_NAME
ORDER BY OT.ORDITEM_QTY DESC
SELECT C.CUST_NAME,P.PROD_DESCRIP
FROM Customer C
JOIN Ord O
ON C.CUST_ID = O.CUST_ID
JOIN OrderItem OT
ON O.ORD_ID = OT.ORD_ID
JOIN Product P
ON OT.PROD_ID = P.PROD_ID
GROUP BY C.CUST_NAME
ORDER BY OT.ORDITEM_QTY DESC