感谢所有花时间评论和回答的人。
-
我有一个这样的价格历史记录表(伪代码):
var status = document.getElementById("status");
var bio = document.getElementById("bio");
其中存储了某些产品的历史价格:
var req = new XMLHttpRequest();
req.open("GET", 'https://api.scratch.mit.edu/users/' + username);
req.send();
req.onreadystatechange = function() {
if (req.readyState === 4 && req.status === 200) {
country.textContent = JSON.parse(req.responseText).profile.country;
avatar.alt = username + "'s avatar";
avatar.src = "https://cdn2.scratch.mit.edu/get_image/user/" + JSON.parse(req.responseText).id + "_90x90.png";
avatar.className = "";
if(JSON.parse(req.responseText).profile.bio !== "") {
bio.textContent = JSON.parse(req.responseText).profile.bio;
}
else {
bio.innerHTML = "<em>Not specified</em>";
}
if(JSON.parse(req.responseText).profile.status !== "") {
status.textContent = JSON.parse(req.responseText).profile.status;
}
else {
status.innerHTML = "<em>Not specified</em>";
}
}};
现在,我想要某些产品在一定时期内的价格。例如。从2018年1月1日到现在。
简单方法:
table price_history (
product_id,
price,
changed_date
)
不好,因为不包括从2018年1月1日到第一次价格变化之间每种产品的单独价格:
1, 1.0, '2017-12-18'
1, 1.2, '2017-12-20'
1, 0.9, '2018-04-20'
1, 1.1, '2018-07-20'
1, 1.3, '2018-07-22'
2, 10.0, '2017-12-15'
2, 11.0, '2017-12-16'
2, 9.9, '2018-01-02'
2, 10.3, '2018-04-04
但是从期初就知道价格至关重要。
因此,除了期间内的价格变动外,还必须包括之前的最后变动。 结果应该是这样的:
SELECT * FROM price_history
WHERE product_id in (1,2) AND changed_date >= 2018-01-01
问:如何指定这样的选择语句?
编辑:
Ajay Gupta的测试场景和解决方案
1, 0.9, '2018-04-20'
1, 1.1, '2018-07-20'
1, 1.3, '2018-07-22'
2, 9.9, '2018-01-02'
2, 10.3, '2018-04-04
获奖选择:
1, 1.2, '2017-12-20'
1, 0.9, '2018-04-20'
1, 1.1, '2018-07-20'
1, 1.3, '2018-07-22'
2, 11.0, '2017-12-16'
2, 9.9, '2018-01-02'
2, 10.3, '2018-04-04
结果:
CREATE TABLE price_history (
product_id integer,
price float,
changed_date timestamp
);
INSERT INTO price_history (product_id,price,changed_date) VALUES
(1, 1.0, '2017-12-18'),
(1, 1.2, '2017-12-20'),
(1, 0.9, '2018-04-20'),
(1, 1.1, '2018-07-20'),
(1, 1.3, '2018-07-22'),
(2, 10.0, '2017-12-15'),
(2, 11.0, '2017-12-16'),
(2, 9.9, '2018-01-02'),
(2, 10.3, '2018-04-04');
我必须承认,这远远超出了我有限的(PG-)SQL技能。
答案 0 :(得分:1)
我想这就是您要寻找的
SELECT Top 1 * FROM price_history WHERE product_id in (1,2) AND changed_date < 2018-01-01
UNION ALL
SELECT * FROM price_history WHERE product_id in (1,2) AND changed_date >= 2018-01-01
答案 1 :(得分:1)
使用Lag
和cte
with cte1 as (
Select *,
lag(changed_date,1,'01-01-1900') over(partition by product_id order by changed_date) as FromDate
from price_history
), cte2 as (
Select product_id, max(FromDate) as changed_date
from cte1
where '2018-01-01' between FromDate and changed_date
group by product_id
)
Select p.*
from price_history p
join cte2 c on p.product_id = c.product_id
where p.changed_date >= c.changed_date;
答案 2 :(得分:0)
如果您确实可以更改表结构,则另一种方法是在表中同时包含start_date和end_date,这样,您的记录将不再依赖于上一行/下一行,并且查询变得更容易编写。参见Slowly changing dimension - Type 2
如果要解决现有结构的问题,在PostgresSQL中,您可以使用LIMIT 1
来获取change_date之前的最新记录:
SELECT
*
FROM
price_history
WHERE
product_id in (1,2)
AND changed_date >= '2018-01-01'
UNION ALL
-- this would give you the latest price before changed_date
SELECT
*
FROM
price_history
WHERE
product_id in (1,2)
AND changed_date < '2018-01-01'
ORDER BY
changed_date DESC
LIMIT 1
答案 3 :(得分:0)
您需要第一个更改日期和所有其他日期>“ 2018-01-01”
select product_id,price, changed_date
from
(
select product_id,price, changed_date,
row_number() over(partition by product_id order by changed_date ) as rn
from price_history
) x
where x.rn = 2 and product_id in (1,2);
union all
select product_id,price, changed_datefrom from price_history
where product_id in (1,2) and changed_date >= '2018-01-01'
答案 4 :(得分:0)
使用union
的解决方案仍然更简单,但在其他答案中却无法正确实现。所以:
SELECT * FROM price_history
WHERE product_id in (1,2) AND changed_date >= '2018-01-01'
union all
(
select distinct on (product_id)
*
from price_history
where product_id in (1,2) AND changed_date < '2018-01-01'
order by product_id, changed_date desc)
order by product_id, changed_date;