Getting Max Value From Joined Table With Certain Logic - sql

This is my table relation :
tbl_product
-----------
product_id
tbl_product_price
-----------------
price_id
price_product_id (FK)
price_normal
price_discount
price_disc_valid_from_date
price_disc_valid_to_date
I'd like to query tbl_product, ordered by its max price DESC, which must be validated first. If the the discount date is still valid (current date between price_disc_valid_from_date AND price_disc_valid_to_date), then get the price_discount. If not valid, then get price_normal. After that I need to get max price ( either from the price_discount or price_normal), then order by that max price.
Most of the questions like this are just how to select the max column, no validation needed first on the joined table.
My question is , what is the postgres sql statement for that query ? Thanks
[EDIT]
I stuck in selecting max price from table tbl_product_price but no idea how to join with tbl_product :
SELECT
pr.price_id, pr.product_price_id,
CASE WHEN current_date BETWEEN pr.price_disc_valid_from_date AND pr.price_disc_valid_to_date
THEN pr.price_discount
ELSE pr.price_normal END AS price
FROM tbl_product_price pr
WHERE pr.price_product_id = 316
GROUP BY pr.price_id, pr.price_product_id
ORDER BY price DESC
LIMIT 1;

Can you do something like this:
SELECT
tbl_tbl_product.price_product_id,
tblMax.MaxPrice
FROM
tbl_tbl_product
JOIN
(
SELECT
tbl_product_price.price_product_id,
MAX(
CASE
WHEN now() BETWEEN
tbl_product_price.price_disc_valid_from_date
AND tbl_product_price.price_disc_valid_to_date
THEN tbl_product_price.price_discount
ELSE tbl_product_price.price_normal
END
) AS MaxPrice
FROM
tbl_product_price
GROUP BY
tbl_product_price.price_product_id
) as tblMax
ON tblMax.price_product_id=tbl_tbl_product.product_id
ORDER BY
tblMax.MaxPrice DESC

If I understand your logic correctly, this query should return products ordered by the maximum price for the product:
SELECT
tp.product_id
FROM
tbl_product tp INNER JOIN tbl_product_price tpp
ON tb.product_id = tpp.price_product_id
GROUP BY
tp.product_id
ORDER BY
MAX(CASE WHEN current_date BETWEEN tpp.price_disc_valid_from_date
AND tpp.price_disc_valid_to_date THEN
tpp.price_discount
ELSE
tpp.price_normal END) DESC

Related

Does it matter to filter results when doing aggregation?

I want to get my sales for each day which is located in my orders_summary table.
orders_summary table columns: id, date, amount, sku_id
products table columns: id, sku
Currently Im getting my daily sales like this:
SELECT
MAX(CASE WHEN os.date = '01/01/2022' THEN COALESCE(amount,0)::INT ELSE 0 END) AS orders_1,
MAX(CASE WHEN os.date = '01/02/2022' THEN COALESCE(amount,0)::INT ELSE 0 END) AS orders_2
FROM products AS p
LEFT JOIN orders_summary AS os ON p.id = os.sku_id
WHERE p.id = '1'
GROUP BY p.id;
Is it important to add AND date BETWEEN '01/01/2022' AND '01/02/2022' in my where clause?
Yes absolutely. Imagine having 10 years worth of data in the table where you're only interested in the data for two days. You must use the where clause which restricts the number of rows (down to 0.05% in this case) before doing the group by.

SQL: Return single value with multiple criteria

Maybe a simple question but I don't get the right results so I hope you can help. In this case I have two different tables, one table filled with Order data (OrderID, Supplier and Order Value). The other table is filled with Invoice data (Invoice ID, Supplier, invoice value, Invoice value -10%, Invoice value +10%).
What I need is an overview based on the order table whereby there is a match between Order supplier and invoice supplier + the order value which is in the range of -10% and +10% of the invoice value. It doesn't matter which order belongs to which invoice, I only need to know whether there is a match 'yes' or 'no'.
Example: In the order table you can see row 1 (order 100). It belongs to supplier A and has a value of 10. In the invoice table you can see that row 4 meets the requirements (Supplier = A and order value: 10 -> range between 9 and 11). This should result in a 'Yes'.
Hope you can help!
Thanks in advance,
Greets!
Order table:
Invoice table:
try:
select *
from Order as o
join Invoice as i
on (o.Supplier = i.Supplier and o.Value between i.ValueMinus10Percent and i.ValuePlus10Percent);
If you just need to now if there is a match, use case with exists. However, I'm going to propose returning a matching invoice id. The value will be NULL if there are no matches:
select o.*,
(select i.id
from invoice i
where i.supplier = o.supplier and
o.value between i.value * 0.9 and i.value * 1.1
fetch first 1 row only
) as a_matching_invoice_id
from orders o
You can do this with a subselect:
select *, (select 1 from Supplier s where o.value - 10 > s.value and o.value + 10 < s.value and so on) as YesOrNo from table Order o;
select a.* into temp from order a,invoice b
where a.supplier=b.supplier and a.value=b.value
select *,case when value between min and max then state='yes'
else state='no'
end
from temp

Get max date (last date sale) column against each item no?

I have following SQL Query which return result
of itemno and no of total quantity sale.I want itemdescripton column against each item no as well.ITEMDESC# column in table invitems.
SQL QUERY :
select INITEMS.ITEMNO,(COUNT(INITEMS.ITEMNO)*COUNT(INITEMS.QTY)) 'Item
Sale',INITEMS.ITEMDESC#1 from InvItems INITEMS
INNER JOIN InvHdr HDR ON INITEMS.INVNO=HDR.INVNO
WHERE INITEMS.TYPE='3'
GROUP BY INITEMS.ITEMNO,INITEMS.ITEMDESC#1
I want max date (last date item sale) column in result.Date column in InvHdr table against each InvNo
As explain in the earlier comments, your query does not works because you have different ITEMDESC for the same ITEMNO
This you "gives" you the result that you want
select INITEMS.ITEMNO,
MAX(INITEMS.ITEMDESC#1) AS 'ITEMDESC',
(COUNT(INITEMS.ITEMNO)*COUNT(INITEMS.QTY)) 'Item Sale'
FROM InvItems INITEMS
INNER JOIN InvHdr HDR ON INITEMS.INVNO = HDR.INVNO
WHERE INITEMS.TYPE = '3'
GROUP BY INITEMS.ITEMNO
But you must check why there are such as in your data. You can list out those ITEMNO that is of such case
SELECT ITEMNO
FROM InvItems
GROUP BY ITEMNO
HAVING MAX(ITEMDESC#1) <> MIN(ITEMDESC#1)
Assuming you are working with an SQL Server version higher than 2005 (which is a pretty safe assumption these days), you can use the over clause with aggregating functions, thus potentially eliminating the need for the group by clause (that is potentially since group by will return distinct results for each value (or set of values) that exists in the group by clause - so you might also need to use distinct:
SELECT initems.itemno,
COUNT(initems.itemno) OVER (PARTITION BY initems.itemno)
* SUM(initems.qty) OVER (PARTITION BY initems.itemno)
FROM InvItems AS initems
WHERE initems.type = '3'

SELECT TOP 10 rows

I have built an SQL Query that returns me the top 10 customers which have the highest outstanding. The oustanding is on product level (each product has its own outstanding).
Untill now everything works fine, my only problem is that if a certain customer has more then 1 product then the second product or more should be categorized under the same customer_id like in the second picture (because the first product that has the highest outstanding contagions the second product that may have a lower outstanding that the other 9 clients of top 10).
How can I modify my query in order to do that? Is it possible in SQL Server 2012?
My query is:
select top 10 CUSTOMER_ID
,S90T01_GROSS_EXPOSURE_THSD_EUR
,S90T01_COGNOS_PROD_NAME
,S90T01_DPD_C
,PREVIOUS_BUCKET_DPD_REP
,S90T01_BUCKET_DPD_REP
from [dbo].[DM_07MONTHLY_DATA]
where S90T01_CLIENT_SEGMENT = 'PI'
and YYYY_MM = '2017_01'
group by CUSTOMER_ID
,S90T01_GROSS_EXPOSURE_THSD_EUR
,S90T01_COGNOS_PROD_NAME
,S90T01_DPD_C
,PREVIOUS_BUCKET_DPD_REP
,S90T01_BUCKET_DPD_REP
order by S90T01_GROSS_EXPOSURE_THSD_EUR desc;
You need to calculate the top Customers first, then pull out all their products. You can do this with a Common Table Expression.
As you haven't provided any test data this is untested, but I think it will work for you:
with top10 as
(
select top 10 CUSTOMER_ID
,sum(S90T01_GROSS_EXPOSURE_THSD_EUR) as TOTAL_S90T01_GROSS_EXPOSURE_THSD_EUR
from [dbo].[DM_07MONTHLY_DATA]
where S90T01_CLIENT_SEGMENT = 'PI'
and YYYY_MM = '2017_01'
group by CUSTOMER_ID
order by TOTAL_S90T01_GROSS_EXPOSURE_THSD_EUR desc
)
select m.CUSTOMER_ID
,m.S90T01_GROSS_EXPOSURE_THSD_EUR
,m.S90T01_COGNOS_PROD_NAME
,m.S90T01_DPD_C
,m.PREVIOUS_BUCKET_DPD_REP
,m.S90T01_BUCKET_DPD_REP
from [dbo].[DM_07MONTHLY_DATA] m
join top10 t
on m.CUSTOMER_ID = t.CUSTOMER_ID
order by t.TOTAL_S90T01_GROSS_EXPOSURE_THSD_EUR desc
,m.S90T01_GROSS_EXPOSURE_THSD_EUR;

select least row per group in SQL

I am trying to select the min price of each condition category. I did some search and wrote the code below. However, it shows null for the selected fields. Any solution?
SELECT Sales.Sale_ID, Sales.Sale_Price, Sales.Condition
FROM Items
LEFT JOIN Sales ON ( Items.Item_ID = Sales.Item_ID
AND Sales.Expires_DateTime > NOW( )
AND Sales.Sale_Price = (
SELECT MIN( s2.Sale_Price )
FROM Sales s2
WHERE Sales.`Condition` = s2.`Condition` ) )
WHERE Items.ISBN =9780077225957
A little more complicated solution, but one that includes your Sale_ID is below.
SELECT TOP 1 Sale_Price, Sale_ID, Condition
FROM Sales
WHERE Sale_Price IN (SELECT MIN(Sale_Price)
FROM Sales
WHERE
Expires_DateTime > NOW()
AND
Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition )
The 'TOP 1' is there in case more than 1 sale had the same minimum price and you only wanted one returned.
(internal query taken directly from #Michael Ames answer)
If you don't need Sales.Sale_ID, this solution is simpler:
SELECT MIN(Sale_Price), Condition
FROM Sales
WHERE Expires_DateTime > NOW()
AND Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition
Good luck!