简体   繁体   中英

SQL match rows based on 2 criteria

I have a dataset of securities prices in a database. The data is structured like this:

id      security_id     time_to_maturity      price
001         01               1.5               100.45
002         01               1.3               101.45
003         01               1.1               102.45
004         01               1.02              101.45
005         01               1.0               101.45
006         03              22.3               94.45
007         03              22.1               96.45
008         03              21.8               98.45
009         05               4.2               111.45
010         05               4.1               112.45
011         05               3.8               111.45
...

id is the row_id and security_id is the id of each security. I am trying to get only data from a certain time range for each security. First I run a query to find the min and max for each security id, then find the difference between the min and max and finally find a value that is 10% more than the minimum like this:

SELECT security_id, MIN(time_to_maturity), MAX(time_to_maturity),
    MAX(time_to_maturity) - MIN(time_to_maturity) tDiff,
    ((MAX(time_to_maturity) - MIN(time_to_maturity)) * .1) + MIN(time_to_maturity)
  FROM db1
  group by security_id
  order by security_id

This gives me the following:

security_id    min()     max()     diff      min+(diff*.1)
  01             1.0        1.5      .5            1.05
  03            21.8       22.3      .5           21.85
  05             3.8        4.2      .4            3.84

Finally what I'd like to do is select from the main data set only those rows for each security_id where the time_to_maturity is < min+(diff*.1) .

I'm not sure how to structure it though as I feel like I need a loop to subset data by security_id, then by time_to_maturity is < min+(diff*.1) .

The answer would look something like this:

id      security_id     time_to_maturity      price
004         01               1.02              101.45
005         01               1.0               101.45
008         03              21.8               98.45
011         05               3.8               111.45

Any suggestions?

SELECT A.id,B.security_id,A.time_to_maturity,A.price
FROM db1 A,
(
SELECT security_id, MIN(time_to_maturity) AS min_time_to_maturity, MAX(time_to_maturity) AS max_time_to_maturity,
    MAX(time_to_maturity) - MIN(time_to_maturity) tDiff,
    ((MAX(time_to_maturity) - MIN(time_to_maturity)) * .1) + MIN(time_to_maturity)
  FROM db1
  group by security_id
  order by security_id
) B
WHERE A.security_id = B.security_id
  AND A.time_to_maturity < (B.min_time_to_maturity+(B.tdiff*0.1));

PS:This will work only in MYSQL.

You didn't say what version of SQL Server you were on, but assuming it's 2005+, you can use a common table expression:

with cte as ( 
    SELECT security_id, 
        ((MAX(time_to_maturity) - MIN(time_to_maturity)) * .1) + MIN(time_to_maturity) as threshold
    FROM db1
    group by security_id
)
select id, db1.security_id, time_to_maturity, price
from db1
inner join cte
   on db1.security_id = cte.security_id
where time_to_maturity < threshold

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM