我有一张桌子,里面有成千上万的水果商品。一些水果商品立即销售,其他水果商品在随后的日期以较低的价格重新定价以清理库存。每个商品条目都有唯一的ID / SKU,但在以新价格重新输入时会获得新的行ID。
Original Table
ID Date UID Fruit Variety Price
1 3/1/18 100100 Apple Fiji 2.99
2 3/1/18 100101 Apple Gala 3.99
3 3/1/18 100102 Apple HoneyCrisp 4.99
4 3/1/18 100201 Orange Navel 2.49
5 3/1/18 100202 Orange Clementine 2.79
6 3/1/18 100301 Cherry Bing 1.99
7 3/1/18 100302 Cherry Black 2.29
8 3/8/18 100100 Apple Fiji 2.69
9 3/8/18 100202 Orange Clementine 2.15
10 3/15/18 100302 Cherry Black 1.79
11 3/22/18 100102 Apple HoneyCrisp 4.49
12 3/29/18 100201 Orange Navel 2.19
我正在寻找输出,其中列出了价格变化的项目,按UID分组,以便重新定价的项目显示在彼此相邻的行中,因此很容易在价格变化中查看比较,像这样:
Desired Results
ID Date UID Fruit Variety Price
1 3/1/18 100100 Apple Fiji 2.99
8 3/8/18 100100 Apple Fiji 2.69
5 3/1/18 100202 Orange Clementine 2.79
9 3/8/18 100202 Orange Clementine 2.15
7 3/1/18 100302 Cherry Black 2.29
10 3/15/18 100302 Cherry Black 1.79
3 3/1/18 100102 Apple HoneyCrisp 4.99
11 3/22/18 100102 Apple HoneyCrisp 4.49
4 3/1/18 100201 Orange Navel 2.49
12 3/29/18 100201 Orange Navel 2.19
谢谢!
答案 0 :(得分:2)
以下内容应该有效:
select t.ID, t.Date, t.UID, t.Fruit, t.Variety, t.Price
from tbl t
join (
select UID
from tbl
group by UID
having count(1) >= 2
) t2
on t2.UID = t.UID
where t.Fruit = 'Apple' -- if you want to filter by a particular fruit
order by t.UID, t.Date
基本上,您只是将表连接到自身的子集,其中该子集表示UID在表中多次出现的任何项。
当然,您需要替换实际的列名和表名。
编辑:窗口函数可能是实现第二个期望结果集的最佳方法:
select q.UID, q.Fruit, q.Variety, avg(percent_drop)
from (
select t.*
, t2.price as reduced_price
, (t.price - t2.price)::NUMERIC(10,2) as price_drop
, (1 - (t2.price / t.price::FLOAT))::NUMERIC(10, 2) as percent_drop
from (
select row_number() over (partition by t.UID order by t.Date), t.*
from tbl t
) t
join (
select row_number() over (partition by t.UID order by t.Date), t.*
FROM tbl t
) t2
on t2.UID = t.UID
and t2.row_number = t.row_number + 1
) q
group by q.UID, q.Fruit, q.Variety
请注意,这会再次将表格与自身联系起来,但这一次它会查找最近的"邻居"排,凭借日期。请注意,无论价格是增加还是减少,此查询都有效,但列别名假设在以后重新添加项目时价格会降低。目前UID,Fruit和Variety的外部查询分组可以查看每个UID基础上的平均%价格下降,但您可以在不执行任何分组的情况下查看所有产品的平均值所有在外部查询。
答案 1 :(得分:2)
我会使用窗口函数来执行此操作:
select ID, Date, UID, Fruit, Variety, Price
from (select t.*,
min(t.price) over (partition by t.fruit, t.variety) as min_price,
max(t.price) over (partition by t.fruit, t.variety) as max_price
from t
) t
where min_price <> max_price
order by fruit, variety, date;
答案 2 :(得分:1)
您可以在子查询上使用 Windows函数的另一种方法。
您可以将条件置于SELECT t.ID, t.Date, t.UID, t.Fruit, t.Variety, t.Price
FROM
(
SELECT uid,ROW_NUMBER() OVER(partition by UID ORDER BY UID, Date) RK
FROM T
)t2 INNER JOIN t t on t.uid = t2.uid AND RK >= 2
order by t.UID, t.Date
条款
然后自我加入。
UUID
sqlfiddle:http://sqlfiddle.com/#!15/755a0/22
答案 3 :(得分:0)
你也可以尝试这样的事情:
WITH FDATA AS(
SELECT 1 "ID", CAST('2018/01/03' AS DATE) DT, 100100 "UID", 'Apple' FRUIT, 'Fiji' VARIETY, '2.99' PRICE FROM DUAL
UNION
SELECT 2 , CAST('2018/01/03' AS DATE) , 100101, 'Apple' , 'Gala' ,'3.99' FROM DUAL
UNION
SELECT 3 , CAST('2018/01/03' AS DATE) , 100102, 'Apple' , 'HoneyCrisp' ,'4.99' FROM DUAL
UNION
SELECT 4 , CAST('2018/01/03' AS DATE) , 100201, 'Orange' , 'Navel' , '2.49' FROM DUAL
UNION
SELECT 5 , CAST('2018/01/03' AS DATE) , 100202, 'Orange' , 'Clementine' ,'2.79' FROM DUAL
UNION
SELECT 6 , CAST('2018/01/03' AS DATE) , 100301, 'Cherry' , 'Bing' , '1.99' FROM DUAL
UNION
SELECT 7 , CAST('2018/01/03' AS DATE) , 100302, 'Cherry' , 'Black' , '2.29' FROM DUAL
UNION
SELECT 8 , CAST('2018/03/08' AS DATE) , 100100, 'Apple' , 'Fiji' , '2.69' FROM DUAL
UNION
SELECT 9 , CAST('2018/03/08' AS DATE) , 100202, 'Orange' , 'Clementine' , '2.15' FROM DUAL
UNION
SELECT 10 , CAST('2018/03/15' AS DATE) , 100302, 'Cherry' , 'Black' , '1.79' FROM DUAL
UNION
SELECT 11 , CAST('2018/03/22' AS DATE) , 100102, 'Apple' , 'HoneyCrisp' , '4.49' FROM DUAL
UNION
SELECT 12 , CAST('2018/03/29' AS DATE) , 100201, 'Orange' , 'Navel' , '2.19' FROM DUAL
UNION
SELECT 13 , CAST('2018/03/10' AS DATE) , 100301, 'Cherry' , 'Bing' , '1.99' FROM DUAL
UNION
SELECT 14 , CAST('2018/03/30' AS DATE) , 100100, 'Apple' , 'Fiji' , '3.19' FROM DUAL
)--SELECT "UID", FRUIT, VARIETY, PRICE, DT, MIN(PRICE) OVER (PARTITION BY UID, FRUIT, VARIETY) MIN_PRICE, MAX(PRICE) OVER (PARTITION BY UID, FRUIT, VARIETY) MAX_PRICE FROM FDATA;
SELECT
"ID", DT, "UID", FRUIT, VARIETY, PRICE
FROM(
SELECT
"ID", "UID", FRUIT, VARIETY, PRICE, DT, MAX(PRICE) OVER (PARTITION BY UID, FRUIT, VARIETY) - MIN(PRICE) OVER (PARTITION BY UID, FRUIT, VARIETY) CHG
FROM FDATA)
WHERE CHG > 0
ORDER BY "UID", DT;