【问题标题】:SQL table and data extractionSQL表和数据提取
【发布时间】:2017-06-19 08:14:12
【问题描述】:

我以前从未做过 SQL,我一直在阅读它。我正在阅读的书中有一个练习让我开始,我还在查找一个名为 W3School 的网站,这本书告诉我尝试以下内容;

交易具有以下结构-

  • trade_id:主键
  • timestamp:交易的时间戳
  • 证券:基础证券(交易中买入或卖出)
  • 数量:基础数量(正表示买入,负表示卖出)
  • 价格:此交易的 1 个证券项目的价格

考虑下表

 CREATE TABLE tbProduct
        ([TRADE_ID] varchar(8), [TIMESTAMP] varchar(8), [SECURITY] varchar(8), [QUANTITY] varchar(8), [PRICE] varchar(8))
    ;

    INSERT INTO tbProduct
        ([TRADE_ID], [TIMESTAMP], [SECURITY], [QUANTITY], [PRICE])
    VALUES
        ('TRADE1', '10:01:05', 'BP', '+100', '20'),
        ('TRADE2', '10:01:06', 'BP', '+20', '15'),
        ('TRADE3', '10:10:00', 'BP', '-100', '19'),
        ('TRADE4', '10:10:01', 'BP', '-100', '19')
    ;

在书中,它告诉我编写一个查询来查找所有发生在 10 秒范围内且价格差异超过 10% 的交易。 结果还应列出两次交易之间价格差异的百分比。

对于一个以前没有做过 SQL 的人来说,读它真的让我很困惑。他们也向我提供了结果,但我不确定他们是如何得出这个结果的。

预期结果:

First_Trade Second_Trade    PRICE_DIFF
TRADE1      TRADE2          25

如果有帮助,我已经创建了一个fiddle。如果有人能告诉我如何得到预期的结果,它将帮助我理解本书的练习。

谢谢

【问题讨论】:

  • 你真正想问的是什么
  • 如果可能的话,有人告诉我得到那个结果。我不确定他们是如何得到这个结果的。谢谢
  • 对不起!! @dave 我没有正确理解你。
  • 别抱歉,也许我没有正确解释。你看到我的小提琴了吗?如果您运行小提琴,它会带回包含所有数据的表格。我正在努力获得我在原始帖子中提出的预期结果。我将如何得到它?如果你看到我正在寻找的粗体字,我希望这是有道理的?
  • 这是一个有趣的问题,以前从来没有这样做过,看看这个stackoverflow.com/questions/17339650/…

标签: sql sql-server sql-server-2008


【解决方案1】:

这会得到你想要的结果。

;with cast_cte
as
(
  select [TRADE_ID], cast([TIMESTAMP] as datetime) timestamp, [SECURITY], [QUANTITY], cast([PRICE] as float) as price
  from tbProduct
)
select t1.trade_id, t2.trade_id, datediff(ms, t1.timestamp, t2.timestamp) as milliseconds_diff,
((t1.price - t2.price) / t1.price) * 100 as price_diff
from cast_cte t1
inner join cast_cte t2
on datediff(ms, t1.timestamp, t2.timestamp) between 0 and 10000
and t1.trade_id <> t2.trade_id
where ((t1.price - t2.price) / t1.price) * 100 > 10
or ((t1.price - t2.price) / t1.price) * 100 < -10

但是,架构和一般查询参数存在许多问题:

1) 列都是 varchars。这是非常低效的,因为它们都需要转换为适当的数据类型才能获得您想要的结果。使用 datetime、int、float 等(我使用 CTE 根据@Jeroen-Mostert 的建议清理查询)

2) 随着表变大,此查询的性能将开始变得很差,因为所使用的谓词(10 秒时间戳)没有被正确索引。

【讨论】:

  • 考虑使用 CTE 来消除查询中的所有强制转换。 (尽管是的,但原始表格的结构还有很多不足之处。)
【解决方案2】:

其他答案的方法略有不同,但效果几乎相同。我使用“Between”来查找日期范围而不是 datediff。

select 
    trade1.trade_ID as TRADE1, 
    trade2.trade_ID as TRADE2, 
    (cast(trade1.price as float)-cast(trade2.price as float))/cast(trade1.price as float)*100  as PRICE_DIFF_PERC 
from 
    tbProduct trade1
inner join 
    tbProduct trade2

on 
    trade2.timestamp between trade1.timestamp and dateadd(s,10,trade1.TIMESTAMP)
and trade1.TRADE_ID <> trade2.TRADE_ID

where (cast(trade1.price as float)-cast(trade2.price as float))/cast(trade1.price as float) >0.1

架构肯定可以改进;消除对“CAST”的需求会使这一点更加清晰:

CREATE TABLE tbProduct2
        ([TRADE_ID] varchar(8), [TIMESTAMP] datetime, [SECURITY] varchar(8), [QUANTITY] int, [PRICE] float)
    ;

允许您这样做:

select *,
    trade1.trade_ID as TRADE1, 
    trade2.trade_ID as TRADE2, 
    ((trade1.price-trade2.price)/trade1.price)*100  as PRICE_DIFF_PERC 
from 
    tbProduct2 trade1
inner join 
    tbProduct2 trade2

on 
    trade2.timestamp between trade1.timestamp and dateadd(s,10,trade1.TIMESTAMP)
and trade1.TRADE_ID <> trade2.TRADE_ID

where (trade1.price-trade2.price) /trade1.price >0.1
    ;

【讨论】:

    【解决方案3】:

    已使用领先功能获得预期结果。试试这个:

    select 
    iq.trade_id as FIRST_TRADE, 
    t1 as SECOND_TRADE, 
    ((price-t3)/price*100) as PRICE_DIFF
    from
    (
     Select trade_id, timestamp, security, quantity, cast(price as float) price,
            lead(trade_id) over (partition by security order by timestamp) t1
            ,lead(timestamp) over (partition by security order by timestamp) t2
            ,lead(cast(price as float)) over (partition by security order by timestamp) t3
     from tbProduct
    ) iq
    where DATEDIFF(SECOND, iq.timestamp,iq.t2) between 0 and 10
    and ((price-t3)/price*100) > 10
    

    这是基于分区是在安全性之上完成的。随时发表评论或提出更正建议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多