mysql在另一个流行值查询的结果中找到一个流行值

时间:2018-06-23 22:27:18

标签: mysql

我有一张充满库存和期权头寸的表格(“期权头寸”是期权到期日和行使价的组合)。列:

userID - the person who owns the position
stock_symbol - the stock they own
call_expiration - expiration date for a call option they've sold against the stock
call_strike - strike price for the same call option

用户可以为同一stock_symbol拥有多个股票头寸,如果确实如此,则他们可能针对该同一品种写有不同的看涨期权。例如,用户399在AAPL中有3个职位,每个职位都有不同的通话选项:

+---------+--------------+-----------------+-------------+
| user_id | stock_symbol | call_expiration | call_strike |
+---------+--------------+-----------------+-------------+
|     399 | AAPL         | 2018-07-20      |         185 |
|     399 | AAPL         | 2018-07-20      |         190 |
|     399 | AAPL         | 2018-08-17      |         180 |
|     399 | X            | 2018-07-20      |          13 |
|     802 | AAPL         | 2018-07-20      |         190 |
|     802 | X            | 2019-01-18      |          14 |
|     802 | MU           | 2018-07-20      |          38 |
|     802 | MIC          | 2018-07-20      |        42.5 |
|     802 | AAPL         | 2018-07-20      |         190 |
|    1079 | MU           | 2018-08-17      |          39 |
|    1079 | X            | 2018-07-20      |          14 |

我想知道哪些股票是最常持有的股票,但我希望每个用户有1票(在上面的数据符号X中获胜,因为其中有3个用户有仓位; AAPL拥有更多仓位,但它们仅由所有者拥有2个用户)。因此,如果同一用户在同一stock_symbol中有多个头寸,则该股票_symbol仅计为1票。如果频率有关联,则按符号字母顺序排序。也许有一种更简单的方法,但这可行:

SELECT stock_symbol, COUNT(*) AS symbol_count FROM 
(SELECT DISTINCT(user_id), stock_symbol FROM user_positions) AS temp
GROUP BY stock_symbol 
ORDER BY symbol_count DESC, stock_symbol ASC LIMIT 10;

然后,我想知道每种流行符号最常用的失效日期。这是我如何为硬编码的stock_symbol(AAPL)找到它的方法。如果有平局,则最早的到期日期将获胜:

SELECT call_expiration, COUNT(*) AS exp_count FROM positions
WHERE stock_symbol='AAPL' 
GROUP BY call_expiration 
ORDER BY exp_count DESC, call_expiration ASC;

然后,最后,我想知道给定符号和到期日期最常见的strike_price。这是我为硬编码符号和有效期找到它的方法。如果有平局,则最低执行价格为准:

SELECT call_strike, COUNT(*) AS strike_count FROM positions
WHERE stock_symbol='AAPL' AND call_expiration = '2018-07-20'
GROUP BY call_strike
ORDER BY strike_count DESC, call_strike ASC;
这些工作,我可以将这些调用放入php脚本中,并循环浏览第一个查询的结果(该查询生成了10个最常用的stock_symbols),但是我想知道是否有办法让mysql来完成所有工作对我来说。

最终目标是一个像这样的表:

popular position #1: S1   E1   K1
popular position #2: S2   E2   K2
popular position #3: S3   E3   K3

位置:

S1 = the most commonly held stock_symbol when each user gets 1 vote
E1 = the most common expiration date across all positions for symbol S1 (if a user has multiple positions for that symbol then you can consider all of them)
K1 = the most common call_strike for all positions where the symbol and expiraiton date are fixed at S1 and E1. (if a user has multiple positions for that symbol then you can consider all of them)

我不确定这是否是一个坏主意,但是我想到了在查询中创建中间列以连接call_expiration + call_strike,或者可能是所有3:symbol + expiration + strike;不能完全弄清楚,因为在第一种情况下(最流行的符号)我希望用户每个人只有1票,但是在接下来的2个查询中(最有效的到期日和该日期的最常见执行价格)可以考虑所有用户位置,即使同一符号的位置超过1个也是如此。在单个查询中可能做太多事情了?

--- 18/6/24在下面添加了示例数据---

CREATE TABLE test_positions (
position_id int unsigned auto_increment,
user_id int unsigned,
stock_symbol varchar(10),
call_expiration date,
call_strike float,
primary key (position_id)
);

INSERT INTO test_positions 
 (user_id, stock_symbol, call_expiration, call_strike)
VALUES 
 (399,  'AAPL', '2018-07-20', 185),
 (399,  'AAPL', '2018-07-20', 190),
 (399,  'AAPL', '2018-08-17', 190),
 (399,  'AAPL', '2018-09-21', 180),
 (399,  'X',    '2018-07-20', 35),
 (802,  'X',    '2018-07-20', 35.5),
 (1079, 'X',    '2018-07-20', 35),
 (1079, 'X',    '2018-07-20', 35.5),
 (1079, 'AAPL', '2018-07-20', 190),
 (1079, 'AAPL', '2018-07-20', 185),
 (1079, 'MRK',  '2018-07-20', 62.5),
 (1079, 'MRK',  '2018-08-17', 60);

使用此数据所需的查询结果是:

+--------------+-----------------+-------------+
| stock_symbol | call_expiration | call_strike |
+--------------+-----------------+-------------+
| X            | 2018-07-20      |          35 |
| AAPL         | 2018-07-20      |         190 |
| MRK          | 2018-07-20      |        62.5 |
+--------------+-----------------+-------------+

因为符号X由3个用户持有。即使APL拥有更多职位,但在APL中只有2个唯一的用户具有职位,因此我们要说X比APL更受欢迎。

在符号X的4个位置中,最常见的call_expiration为2018-07-20,如果我们查看所有符号为X且call_expiration为2018-07-20的call_strikes,则其为平局(2有35和2的值为35.5),因此我们要选择2中的较低者。

在MRK的2个职位中,它与call_expiration并列(两个日期各1个),因此我们选择2个中的较早者(2018-07-20),然后查看符号MRK,其中call_expiration为2018-07-20最常见(唯一)call_strike为62.50。

0 个答案:

没有答案