是否可以编写一个MySQL查询,从符合特定条件的那一行中选择一行中的所有项目?
例如,要获得“估值”的价格。大于5:
Date Price Valuation
01/06/2016 9.2 9
31/05/2016 9.3 5
27/05/2016 9.5 8
26/05/2016 9.7 7
25/05/2016 9.5 8
24/05/2016 9.3 4
23/05/2016 9.2 3
20/05/2016 9.2 5
19/05/2016 8.9 9
18/05/2016 9.1 4
17/05/2016 9.2 9
但是,在估值升至5以上之后,您将如何获得价格?
SynchronizationContext.Current
在这个例子中,它将是9.3,9.5,9.7,9.2和9.1
编辑:如果有帮助,可以将索引列添加到表中。
编辑"一天后"我的意思是表格中的下一行(而不是按时间顺序排列的第二天)
答案 0 :(得分:1)
我们假设我们有
CREATE TABLE quotes(
`date` date not null primary key,
price numeric(5,1) not null,
valuation integer not null
);
INSERT INTO quotes VALUES
('2016-06-01', 9.2, 9),
('2016-05-31', 9.3, 5),
('2016-05-27', 9.5, 8),
('2016-05-26', 9.7, 7),
('2016-05-25', 9.5, 8),
('2016-05-24', 9.3, 4),
('2016-05-23', 9.2, 3),
('2016-05-20', 9.2, 5),
('2016-05-19', 8.9, 9),
('2016-05-18', 9.1, 4),
('2016-05-17', 9.2, 9);
然后,以下SELECT
语句可以解决问题:
SELECT basedate, quotes.*
FROM
(
SELECT basedate, min(date) AS nextDate
FROM
(
SELECT * FROM
(SELECT date as basedate FROM quotes WHERE Valuation > 5) as dates
LEFT JOIN quotes ON dates.basedate < quotes.date
) as aggrtable
GROUP BY basedate
) as fullTable
LEFT JOIN quotes ON fullTable.nextDate = quotes.date;
让我们从内到外检查这个:
SELECT
语句检索对所有VALUATION > 5
感兴趣的引号。那些条件成立的日期在这里被称为basedate
。aggrtable
确定日期,这些日期在基准日期“之后”,但最接近基准日期(使用min
聚合功能)。quotes
检索值,结果将再次与原始表连接,使连接条件位于基准日期的“最小最近日期”。注意:在大型表之间,这种非等式连接可能会变得丑陋:假设我们在数据库中有几十年的日期。在第二天,估值超过5.然后,这个非equi联接将生成结果中除前两个之外的所有日期。因此,如果您运气不好,这可能会导致O(n²)
记录,这些记录需要暂时生成,然后通过min
上的聚合再次压缩。因此,您的结果集最多只会有O(n)
条记录,但可能需要O(n²)
时间/空格。您也可以使用EXPLAIN
语句对此讨论进行交叉检查;在那里你会发现一个EXTRA = "Using temporary, Using filesort"
,这在性能方面是非常邪恶的。
答案 1 :(得分:0)
如果只是想在估值高于五的任何日期之后立即找到日期/价格/估值,无论前几天的估值如何,都要使用:
select * from T
where Date in (
select min(t2.Date)
from T t1 inner join T t2 on t2.Date > t1.Date
where t1.Valuation > 5
group by t1.Date
)
解释:查找估值高于5的天数。在每个实例中,执行自联接以查找所有日期,并仅保留最早的日期。现在返回该日期列表的所有数据。如果你可以给它一个上限,就像从来不需要看一周以上那样,自联接会更快。
如果您正在寻找估值转换,那就更复杂了:
select * from T
where `Date` in (
select t2.`Date`
from T t1 inner join T t2
on t2.`Date` > t1.`Date`
and t2.`Date` < date_add(t1.`Date`, interval 7 day) /* bound for performance */
where
/* valuation starts at or below 5 */
t1.Valuation <= 5
/* did we find the day after the next day? */
and 3 = (
select count(*) from T t3
where t3.`Date` between t1.`Date` and t2.`Date`
)
/* did the valuation rise above 5 on the day in between */
and 5 < (
select t4.Valuation from T t4
where t4.`Date` > t1.`Date` and t4.`Date` < t2.`Date`
)
)
超越我首先相信你正在寻找从五岁以下到五岁以上的过渡。然后你想要那个之后的那天的价格。这种解释似乎与您的样本数据不匹配。
这是一个在SQL Server上测试查询的地方。 http://rextester.com/BQFJDE14701
答案 2 :(得分:0)
您基本上想要先前的估值。一种方法使用变量,另一种方法使用相关子查询:
select p.*,
(select p2.valuation
from prices p2
where p2.date < p.date
order by p2.date desc
limit 1
) as prev_valuation
from prices p;
现在您只想添加先前估值的条件大于5. MySQL允许您使用having
子句执行此操作:
select p.*,
(select p2.valuation
from prices p2
where p2.date < p.date
order by p2.date desc
limit 1
) as prev_valuation
from prices p
having prev_valuation > 5;