how to use mysql function "min()" with two criteria in one query - mysql

I have a table of items some are second hand and some are new,
I would like a query giving me the minimum price for the new version of the item as well as the second hand version.
I have a boolean field called "new" who tell if the item is second hand or not
for the result I have to do two query but I think its possible to do only one
query for the second hand :
SELECT ref_product, MIN( price )
FROM item_list
WHERE new = 0
GROUP BY ref_produit
query for the new :
SELECT ref_product, MIN( price )
FROM item_list
WHERE new = 1
GROUP BY ref_produit
I would like that kind of result :
ref_product | min_price_for _secondhand | min_price_for_new

SELECT ref_product,
MIN(case when new = 1 then price else null end) as new_price,
MIN(case when new = 0 then price else null end) as used_price
FROM item_list
GROUP BY ref_product

Try something like:
SELECT ref_product, MIN( price )
FROM item_list
WHERE new in (0,1)
GROUP BY new, ref_product

Drop the condition on new (get all products) and group by ref_produit' then bynew`:
SELECT ref_product, new, MIN(price) AS min_price
FROM item_list
GROUP BY ref_produit, new

Related

How to calculate quantity on hand for every lot (mysql)

This is the transaction details table
I am trying to design a Mysql inventory database.
I consider every type: 1 row a product lot (batch).
The type column has 1 for IN and 0 for OUT for each transaction.
detail_id is referencing the id column.
How can I get this result:
id item sum(quantity)
1 1 3 [10-(5+2)]
4 1 0 (5-5)
6 2 20 20
WITH cte AS (
SELECT *,
SUM(detail_id IS NULL) OVER (PARTITION BY item ORDER BY id) group_num
FROM details
)
SELECT MIN(id) id,
item,
SUM( CASE type WHEN 1 THEN quantity
WHEN 0 THEN -quantity
END ) `sum(quantity)`
FROM cte
GROUP BY item, group_num;
fiddle
You can use this:
SELECT
lots.id,
MIN(lots.item) AS item,
MIN(lots.quantity) - IFNULL(SUM(details.quantity), 0) AS quantity
FROM (
SELECT id, item, quantity
FROM details
WHERE type = 1
) lots LEFT JOIN details ON lots.id = details.detail_id
GROUP BY lots.id
ORDER BY lots.id
demo on dbfiddle.uk
I have modified your fiddle. I did change one thing to your existing table - you need to specify detail_id, wherever it is null, so that we can group the result on that.
Final query will look like
select detail_id, item,
(in_sum - out_sum) as `sum(quantity)` from
(SELECT
detail_id,
item,
sum(case when type=1 then quantity else 0 end) as in_sum,
sum(case when type=0 then quantity else 0 end) as out_sum
FROM details
group by detail_id, item) tab
Firstly getting the sum of quantity for specified type by grouping over detail_id, item and then use that result to compute the final output.

Comparing day and week prices and getting cheapest

I'm trying to get the lowest price of an object. Problem is there can be daily and weekly prices. So when searching for the cheapest price i have to multiply the day price time 7 and compare to the week price to get the cheapest.
It can also happen that an object has week prices only or day prices only (or no prices at all).
BTW: It has to be such a subselect query, cause i have some more WHERE queries following later.
Pricetable
id price type oid
1 10 d 1
2 12 d 2
3 70 w 1
4 80 w 2
Objects
id name
1 house1
2 house2
This is what i'm using but its not working correctly. When the day price*7 is bigger that the week price it still gives me the day price.
SELECT p.oid, p.price, p.id, p.type FROM Pricetable p INNER JOIN (
SELECT oid, MIN(IF(type="w",price, price*7)) AS price, id, type
FROM Pricetable
GROUP BY oid
) p2 ON p.oid = p2.oid AND p.id= p2.id
Your query should work to get the minimum price. However, it should be written as:
SELECT oid, MIN(CASE WHEN type = 'w' THEN price ELSE 7*price END) AS price
FROM Pricetable
GROUP BY oid ;
If you want other values from row with the minimum price, then you need more logic. How about this?
SELECT pt.*oid, MIN(CASE WHEN type = 'w' THEN price ELSE 7*price END) AS price
FROM Pricetable pt
WHERE pt.id = (SELECT pt2.id
FROM PriceTable pt2
WHERE pt2.oid = pt.oid
ORDER BY (CASE WHEN pt2.type = 'w' THEN pt2.price ELSE 7*pt2.price END)
LIMIT 1
);
You'll need a sub-select with some sort of ranking to get the cheapest price.
Check https://dba.stackexchange.com/questions/13703/get-the-rank-of-a-user-in-a-score-table That should get you on the right track.
I don't have access to MySQL right now, and it's a bit different than MSSQL. But that link should set you on the path.

MySQL Query issue - Adding additional and totaling

I have written the following query which is design the multiply the total quantity of products, against quantity price and put this into a new column. What I am wondering and a bit stuck with. Is there then a way to also total this new column. So I as well as getting a total for each row ordered, I can also get a total for the order itself.
SELECT Product_Quantity, ProductPrice, (Product_Quantity*ProductPrice) as Total FROM Order_Info WHERE Order_Number = '1'
This add a record with a total.
Simulates GROUP BY with ROLLUP
SELECT
Product_Quantity
, ProductPrice
, (Product_Quantity*ProductPrice) AS Total
FROM
Order_Info
WHERE
Order_Number = '1'
UNION ALL
SELECT
NULL
, NULL
, SUM((Product_Quantity*ProductPrice)) AS Total
FROM
Order_Info
WHERE
Order_Number = '1'
To get a summary row, you can use sql's union and the sum aggregating function. Try this:
SELECT Product_Quantity, ProductPrice, (Product_Quantity*ProductPrice) as Total FROM Order_Info WHERE Order_Number = '1'
union all
SELECT sum(Product_Quantity), sum(ProductPrice), sum(Product_Quantity*ProductPrice) as Total FROM Order_Info WHERE Order_Number = '1'

Mysql join where value or null

I've got a table PROD
ID NAME
1 Apple
2 Banana
And the relative table PRICES , with global prices (ID_USER is Null)
or per-user prices (ID_USER)
PROD_ID USER_ID PRICE
1 null 10
1 5 8
Now, i need a query that finds all products and the relative prices,
the catch is that i'm trying to retrieve the user price only if there is one, else retrieve the global price
SELECT PROD.* , PRICES.* FROM PROD
LEFT JOIN PRICES ON PROD.ID_PROD = PRICES.ID_PROD
WHERE PRICES.USER_ID IS NULL OR PRICES.USER_ID = 5
This query returns 2 rows (the prod joined with the 2 prices)
Is there a way to retrieve the exact price for the product in just one query ?
thanks !!
EDIT: In the join i need the per-user price row (the last one) only if the row exists , else i need to retrieve the row with the global price, is that possible ?
SELECT
prod.*,
COALESCE(p_user, p_default) As Price
FROM
Prod INNER JOIN (SELECT
PROD_ID,
MAX(CASE WHEN USER_ID=5 THEN Price END) p_user,
MAX(CASE WHEN USER_ID IS NULL THEN Price END) p_default
FROM
Prices
GROUP
BY PROD_ID) m_uid
ON Prod.ID = m_uid.Prod_ID
Please see fiddle here.

Determining values based on the count of that item in

I have two tables. ticket & ticketlist.
The sold out column in the ticket table needs to be 1 if that item is sold out.
Table ticket needs to be soldout when the count for that item in table ticketlist is 2.
ticket
ticketid, quantity, soldout
21 2 1
ticketlist
ticketlistid, ticketid
3 21
4 21
The logic is:
soldout should be '1' if ticket.quantity - (COUNT(ticketlist.ticketlistid) WHERE ticket.ticketid = ticketlist.ticketlistid) > 0
This is the MySQL that I tried
UPDATE ticket
SET soldout = '1'
WHERE quantity - (SELECT ticket.ticketid, COUNT(ticketlist.ticketlistid)
FROM ticket, ticketlist
WHERE ticket.ticketid = ticketlist.ticketid) > '0';
Any help will be appreciated.
In your subselect:
You should only return one column.
Don't select the same table you already have from your update.
You probably also want to set sold_out to one when quantity - (SELECT ...) <= 0, rather than > 0 as you are currently doing.
Change the query to this:
UPDATE ticket
SET soldout = '1'
WHERE quantity - (
SELECT COUNT(ticketlist.ticketlistid)
FROM ticketlist
WHERE ticket.ticketid = ticketlist.ticketid
) > 0;
Also your database is denormalized. You are storing information in one table that can be derived from the data in another table. This redundancy can cause errors if the two ever get out of sync. I'd recommend only doing this if you need it for performance reasons.
You're better of implementing this as a view, otherwise risk the soldout number being out of sync.
CREATE VIEW vw_tickets AS
SELECT t.ticketid,
t.quantity,
COUNT(*) AS sold,
CASE
WHEN t.quantity = COUNT(*) THEN 1
WHEN t.quantity < COUNT(*) THEN -1 -- oversold
ELSE 0
END AS soldout
FROM TICKET t
LEFT JOIN TICKETLIST tl ON tl.ticketid = t.ticketid
GROUP BY t.ticketid, t.quantity
One problem I see is this:
(SELECT ticket.ticketid, COUNT(ticketlist.ticketlistid)
FROM ticket, ticketlist
WHERE ticket.ticketid = ticketlist.ticketid)
You are testing the result of that query against "> 0" however, it returns ticketid and count. You need to removed ticket.ticketid.
Try this:
UPDATE `ticket`
SET `soldout` = 1
WHERE `ticketid` IN (
SELECT `ticketid` FROM `ticketlist` GROUP BY `ticketid` HAVING COUNT(`ticketlistid`) = 2 )