SQL get previous price and price changed - mysql

Basically the excel look like this.
enter image description here
Now I've got current date & prices by myself:
SELECT p.item as Item, p.Cost as CurrentCost, p.CostDate as CurrentCostDate
FROM price_change.`question 3 data` p
inner join (
SELECT item, max(CostDate) as CurrentDate
FROM price_change.`question 3 data`
group by item
)pc on p.item = pc.item and p.CostDate = pc.CurrentDate
I wanted to get the most recent prices in every item, my thought is:
use rank() over to get the rank in every item order by date, then according to the rank to get the most recent price but I don't know how to do it.

SELECT item, CostDate,
FIRST_VALUE(Cost) OVER (PARTITION BY item ORDER BY CostDate DESC)
FROM price_change.`question 3 data`

Related

SQL SELECT MIN value with WHERE statement

I'm trying to get the lowest price of a specific quote on SQL. I tried the following with erroneous results:
SELECT * FROM price WHERE price=(SELECT MIN(price) as price FROM price WHERE id_quote=36
SELECT id_provider, MIN(price) as price FROM price WHERE id_quote=36
I understand that I'm getting multiple results on the first query if I have the same price in that table regardless of the quote. But I don't know why the second isn't giving me the correct results.
I need to call only id_provider and its price from that specific quote (no group).
Any help?
I think you just need a correlated subquery:
SELECT p.*
FROM price p
WHERE p.id_quote = 36 AND
p.price = (SELECT MIN(p2.price) FROM price p2 WHERE p2.id_quote = p.id_quote);
Notice that the "quote" condition has moved to the outer query.
I like using RANK() for this kind of problem:
SELECT id_quote, id_provider, price
FROM
(
SELECT id_quote id_provider, price,
RANK() OVER(PARTITION BY id_quote ORDER BY price ASC) AS rnk
FROM price
) sub
WHERE rnk = 1
You can do it this way if you want:
SELECT TOP 1 id_provider, price FROM price WHERE id_quote=36 ORDER BY price ASC

Choosing Correct Dates

Please excuse my formatting... I am working on that.
I am trying to select the correct price of a project in my query based off the appropriate effective date.
For example we have a table that has the following information
Price Table-------------------------
Item Price effectiveDate
A $0.57 1/1/17
A $0.72 6/1/17
Now I have a production table that contains what was produced that day and it will list out their quantity and the production for a production date.
Production Table-------------------
Item Quantity productionDate
A 100 2/1/17
A 100 7/1/17
Now when I query these I want to be able to select the appropriate price given the productionDate and effectiveDate.
What is the best way to achieve this?
Try the following (first select the highest effectiveDate lower than the productionDate, then get the price for that date):
SELECT preselection.Item, Price FROM
(SELECT Production.Item, Max(effectiveDate) As MaxEffectiveDate
FROM Production INNER JOIN Price ON Price.item = Production.Item
Where Price.effectiveDate <= productionDate GROUP BY Production.Item) As preselection
INNER JOIN Price ON Price.Item = preselection.Item
AND Price.effectiveDate = preselection.MaxEffectiveDate

Group By column, returning most recent AND earliest fields

I have a table:
ITEM NOTE RECORD_DATE USER
Apple Blah 2016-12-30 11:22:33 mcmurphy510
Orange Somenote 2016-12-31 11:22:33 user2
Apple BlahBlah 2017-01-01 11:22:33 user2
I'm trying to create a query that will show the Item, and most recent Note. I also need to derrive four fields from the DATE and USER columns:
CREATED: should be the RECORD_DATE timestamp of the earliest row for given ITEM
CREATED_BY: should be the USER of the earliest row for given ITEM
UPDATED: should be the RECORD_DATE timestamp of the most recent row for given ITEM
UPDATED_BY: should be the USER of the most recent row for given ITEM
I've managed to get one or the other (either earliest or latest), but not both, using the following query:
SELECT
i.item,
i.note,
i.record_date AS created,
i.user AS created_by
FROM
item i
INNER JOIN (
SELECT
item,
MAX(record_date) as record_date
FROM item
GROUP BY item
) i2
ON (
i.item = i2.item AND
i.record_date = i2.record_date
)
Using this, I can switch between returning the earliest and most recent RECORD_DATE by switching between MAX() and MIN() in the sub query.
My question is how can I create a signle query that can show both the earliest AND most recent results in the same row?
Desired Result:
ITEM NOTE CREATED CREATED_BY UPDATED UPDATED_BY
Apple BlahBlah 2016-12-30 11:22:33 mcmurphy510 2017-01-01 11:22:33 user2
Orange Somenote 2016-12-31 11:22:33 user2 NULL NULL
I have a fiddle up here:
http://sqlfiddle.com/#!9/cd724a/3
You can find earliest and latest date for each item and then join with the main table like this:
select
i1.item,
i2.note,
i1.record_date created_date,
i1.user create_user,
case when i1.record_date <> i2.record_date then i2.record_date end update_date,
case when i1.record_date <> i2.record_date then i2.user end update_user
from item i1
inner join item i2
on i1.item = i2.item
inner join (
select item, min(record_date) mn, max(record_date) mx
from item
group by item
) i3 on i1.item = i3.item
and i1.record_date = i3.mn
and i2.record_date = i3.mx;
SQLFiddle
You could calculate first and last at once and use them both in the join criteria, like so:
SELECT i.item, i.note, i.record_date AS created, i.user AS created_by
FROM item i
INNER JOIN (
SELECT item
, MAX(record_date) as lastDate
, MIN(record_date) as firstDate
FROM item
GROUP BY item
) AS flDates
ON i.item = flDates.item
AND i.record_date IN (flDates.firstDate, flDates.lastDate)
or, you might get a faster query by using a UNION on the subquery and avoid the index-wasting OR implied by the above's IN condition, like so:
SELECT i.item, i.note, i.record_date AS created, i.user AS created_by
FROM item i
INNER JOIN (
SELECT item, MIN(record_date) as record_date
FROM item
GROUP BY item
UNION
SELECT item, MAX(record_date) as record_date
FROM item
GROUP BY item
) AS flDates
ON i.item = flDates.item AND i.record_date = flDates.record_date
If the table has an index on (item, record_date), it is more likely to be faster than the first version; but without such an index the separate calculation of MIN and MAX values could end up taking longer.

MySQL Group by Sum Total

I'm getting an error when trying to group by a sum value.
select sum(price + adjustments) as adjusted_price from items group by adjusted_price
Is this not possible?
Example: I want to grab items that have the same adjusted price. Example ( $1.00 - .50 = .50) --- ( $2.00 - 1.50 = .50), I want to grab items that have .50 grouped together.
Thanks
Maybe you are looking for the grand total adjusted_price? If so you don't need the groupby
select
sum(adjusted_price)
from
(select price+adjustments as adjusted_price from items) tt
Edit:
Sounds like you want to group by the adjusted_price. Try the following which will return the frequency count as well:
select
adjusted_price, count(1)
from
(select price+adjustments as adjusted_price from items) tt
group by adjusted_price
Or the following should get you only the unique adjusted_price values:
select distinct
adjusted_price
from
(select price+adjustments as adjusted_price from items) tt
Is this not possible?
Forget about possibility, moreover that looks wrong and incorrect. Why you are trying to group by the SUM() result BTW? You should rather group by any other column in your table. something like below but can't say for sure unless see your table schema and sample data.
select sum(price) + sum(adjustments) as adjusted_price
from items
group by some_column_name;

Subquery in mysql looking for in the same table

I have one table with this headers
id city date item
I am interested in identify the id with the same item in the same month and count how many items repeated receive in the same month. So my query in mysql is:
select a.id, concat(a.id, month(a.date), a.item) as a from table
where a = (select concat(b.id, month(b.date), b.item) as b from table)
group by a.id
having count(a=b)>=1
But that query take too much time and may not work, could you help me?
You haven't reacted to the comments made three hours ago. But from your comments to Seth McClaine's answer I read that you want a list of rows showing id (which despite its name is not the table's unique ID!), month, item, and the number of occurences.
One row per id, month and item means: group by id, month, item.
Use a HAVING clause in order to only show occurences > 1.
select id, month(date), item, count(*)
from mytable
group by id, month(date), item
having count(*) > 1;
Well, this is about what Seth McClaine already told you. And while you commented on his answer, you didn't say what is missing from it for you to accept it.
I think you should be able to do something like this, giving you the count total of items with matching id, month, and item
Select Count(*) as total, month(date) as month, item, id
From table
group by (item, month(date), id)