If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

 
Go Back  dBforums > Database Server Software > MySQL > 'having' question

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 09-11-09, 21:24
moosie moosie is offline
Registered User
 
Join Date: Sep 2009
Posts: 4
'having' question

Hi folks. I thought I understood the 'having' clause. Guess not. Consider the following data:

| code | lstrike | sstrike |
+------+---------+---------+
| 1 | 20.00 | 22.50 |
| 0 | 20.00 | 22.50 |
| 1 | 22.50 | 25.00 |

Notice rows 1 and 2 are duplicates except for the code. I want all of these logical dupes condensed down to single rows, those with the lowest code.

I thought I could do this, but it's not working:

select code, lstrike, sstrike from aa group by lstrike, sstrike having code=min(code)

To be clear, in the above example, I want the result set to be rows 2 and 3, which are both the minimum code for their respective lstrike/sstrike pairs.

Thanks in advance.
Reply With Quote
  #2 (permalink)  
Old 09-11-09, 22:45
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,534
you spoke of "rows" rather than values, so i'm going to guess that there might be additional columns involved, in which case you need this type of query --
Code:
SELECT aa.code
     , aa.lstrike
     , aa.sstrike    
     , aa.other_columns  
  FROM ( SELECT MIN(code) AS min_code
              , lstrike
              , sstrike 
           FROM aa
         GROUP
             BY lstrike
              , sstrike ) AS mmm
INNER
  JOIN aa
    ON aa.code    = mmm.min_code    
   AND aa.lstrike = mmm.lstrike 
   AND aa.sstrike = mmm.sstrike
if those three really are the only columns in the table, then you can simplify it to this --
Code:
SELECT MIN(code) AS code    
     , lstrike                  
     , sstrike                  
  FROM aa                       
GROUP                           
    BY lstrike                  
     , sstrike
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #3 (permalink)  
Old 09-12-09, 00:42
moosie moosie is offline
Registered User
 
Join Date: Sep 2009
Posts: 4
Thanks for the response Rudy.
Sigh, yes there are more columns, and in the interest of providing a simple example, I went too far. And now I need to probably go too far the other way to explain why I don't know how to apply your (correct) answer to my situation:

Code:
drop table s;
drop table o;
create table s (
  ticker varchar(12),
  last decimal(6,2)
) engine=innodb;

create table o (
  sticker varchar(12),
  strike decimal(6,2)
) engine=innodb;

insert into s values('EBAY', 23.91);

insert into o values('EBAY', 5.00);
insert into o values('EBAY', 7.50);
insert into o values('EBAY', 10.00);
insert into o values('EBAY', 12.50);
insert into o values('EBAY', 14.00);
insert into o values('EBAY', 15.00);
insert into o values('EBAY', 16.00);
insert into o values('EBAY', 17.50);
insert into o values('EBAY', 19.00);
insert into o values('EBAY', 20.00);
insert into o values('EBAY', 21.00);
insert into o values('EBAY', 22.50);
insert into o values('EBAY', 24.00);
insert into o values('EBAY', 25.00);
insert into o values('EBAY', 26.00);
insert into o values('EBAY', 27.50);
insert into o values('EBAY', 30.00);
insert into o values('EBAY', 35.00);
insert into o values('EBAY', 37.50);
insert into o values('EBAY', 40.00);
insert into o values('EBAY', 45.00);
insert into o values('EBAY', 50.00);
insert into o values('EBAY', 55.00);
insert into o values('EBAY', 60.00);
insert into o values('EBAY', 65.00);
Stocks and options. Using EBAY as the example, inserted into the options table are the strike prices for call options expiring Jan 2010. My goal is to create rows containing two different strikes (for a potential 'spread' option trade). The acceptable strike pairs are defined by the conditions in this next query. The idea is that there are 'categories' of pairs ranging from 'V'ery conservative, through 'A'ggressive in terms of the trading strategy. The scale is V, C, M, A, where C is Conservative, and M is moderate.

Code:
select profile, code, l_strike, s_strike
from (

select 'V' profile, 3 code, a.strike l_strike, b.strike s_strike
from o a, o b, s
where a.sticker=b.sticker and a.sticker=s.ticker and
          s.ticker='EBAY' and a.strike <= s.last - '2.50' and
          a.strike >= s.last - ('2.50' * 3) and b.strike >= a.strike + '2.50' and
          b.strike <= a.strike + ('2.50' * 3)

UNION ALL

select 'C' profile, 1 code, a.strike l_strike, b.strike s_strike
from o a, o b, s
where a.sticker=b.sticker and a.sticker=s.ticker and
          s.ticker='EBAY' and a.strike <= s.last and
          a.strike >= s.last - ('2.50' * 2) and b.strike >= a.strike + '2.50' and
          b.strike <= a.strike + ('2.50' * 3)

UNION ALL

select 'M' profile, 0 code, a.strike l_strike, b.strike s_strike
from o a, o b, s
where a.sticker=b.sticker and a.sticker=s.ticker and s.ticker='EBAY' and
          a.strike <= s.last + '2.50' and a.strike >= s.last - '2.50' and
          b.strike >= a.strike + '2.50' and b.strike <= a.strike + ('2.50' * 3)

UNION ALL

select 'A', 2 code, a.strike l_strike, b.strike s_strike
from o a, o b, s
where a.sticker=b.sticker and a.sticker=s.ticker and s.ticker='EBAY' and
          a.strike <= s.last + ('2.50' * 2) and a.strike >= s.last  and
          b.strike >= a.strike + '2.50' and b.strike <= a.strike + ('2.50' * 3)

) 

AS m

+---------+------+----------+----------+
| profile | code | l_strike | s_strike |
+---------+------+----------+----------+
| V       |    3 |    17.50 |    20.00 | 
| V       |    3 |    17.50 |    21.00 | 
| V       |    3 |    17.50 |    22.50 | 
| V       |    3 |    19.00 |    22.50 | 
| V       |    3 |    20.00 |    22.50 | 
| V       |    3 |    17.50 |    24.00 | 
| V       |    3 |    19.00 |    24.00 | 
| V       |    3 |    20.00 |    24.00 | 
| V       |    3 |    21.00 |    24.00 | 
| V       |    3 |    17.50 |    25.00 | 
| V       |    3 |    19.00 |    25.00 | 
| V       |    3 |    20.00 |    25.00 | 
| V       |    3 |    21.00 |    25.00 | 
| V       |    3 |    19.00 |    26.00 | 
| V       |    3 |    20.00 |    26.00 | 
| V       |    3 |    21.00 |    26.00 | 
| V       |    3 |    20.00 |    27.50 | 
| V       |    3 |    21.00 |    27.50 | 
| C       |    1 |    19.00 |    22.50 | 
| C       |    1 |    20.00 |    22.50 | 
| C       |    1 |    19.00 |    24.00 | 
| C       |    1 |    20.00 |    24.00 | 
| C       |    1 |    21.00 |    24.00 | 
| C       |    1 |    19.00 |    25.00 | 
| C       |    1 |    20.00 |    25.00 | 
| C       |    1 |    21.00 |    25.00 | 
| C       |    1 |    22.50 |    25.00 | 
| C       |    1 |    19.00 |    26.00 | 
| C       |    1 |    20.00 |    26.00 | 
| C       |    1 |    21.00 |    26.00 | 
| C       |    1 |    22.50 |    26.00 | 
| C       |    1 |    20.00 |    27.50 | 
| C       |    1 |    21.00 |    27.50 | 
| C       |    1 |    22.50 |    27.50 | 
| C       |    1 |    22.50 |    30.00 | 
| M       |    0 |    22.50 |    25.00 | 
| M       |    0 |    22.50 |    26.00 | 
| M       |    0 |    22.50 |    27.50 | 
| M       |    0 |    24.00 |    27.50 | 
| M       |    0 |    25.00 |    27.50 | 
| M       |    0 |    22.50 |    30.00 | 
| M       |    0 |    24.00 |    30.00 | 
| M       |    0 |    25.00 |    30.00 | 
| M       |    0 |    26.00 |    30.00 | 
| A       |    2 |    24.00 |    27.50 | 
| A       |    2 |    25.00 |    27.50 | 
| A       |    2 |    24.00 |    30.00 | 
| A       |    2 |    25.00 |    30.00 | 
| A       |    2 |    26.00 |    30.00 | 
| A       |    2 |    27.50 |    30.00 | 
| A       |    2 |    27.50 |    35.00 | 
+---------+------+----------+----------+
The pairing conditions overlap, so for many pairs there are two acceptable designations, for instance l_strike/s_strike 20.00/22.50 is represented in both a 'C' row and a 'V' row. The codes correspond with the profile (VCMA) such that the minimum of any pair (of codes) will collapse toward 'moderate' (toward zero). I want the result set above, but with only the minimum code that represents any particular pair of strikes. No 'duplicate' pairs.

So, given all this, I don't know how to apply your answer, because the dataset isn't a table that I can subquery/self-join, but the result of a join on the fly.

Sorry for the length of this post, I hope the explanation is clear enough.
Thanks again for taking the time.
-joe

Last edited by moosie; 09-12-09 at 00:50.
Reply With Quote
  #4 (permalink)  
Old 09-12-09, 05:21
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,534
your query looks like this --
Code:
SELECT profile, code, l_strike, s_strike
  FROM (
       /* a bunch of stuff */
       ) AS m
change it to this --
Code:
SELECT MIN(code) AS code, l_strike, s_strike
  FROM (
       /* a bunch of stuff */
       ) AS m
GROUP
    BY l_strike, s_strike
it is possible to modify this SQL further, to stick the VCMA back on depending on the minimum code, if you need to

__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #5 (permalink)  
Old 09-12-09, 10:15
moosie moosie is offline
Registered User
 
Join Date: Sep 2009
Posts: 4
Quote:
Originally Posted by r937
it is possible to modify this SQL further, to stick the VCMA back on depending on the minimum code, if you need to
Yes, I would like to have this. This is exactly what I haven't been able to do (or I guess to explain very well

I'm open to suggestions if I'm going down a stupid path. But yes, I want the VCMA for the display. The code is just a way to rank the VCMA. There really are only the four V-C-M-A values (with a UNION for each, ugh). So, if I need a tiny table:
Code:
create table profile (
  name char(1),
  code integer(1)
)
this would be fine, but I can't figure out how to join it to the min_code in the current result set. This is what led me down the path of thinking I could use HAVING.
Reply With Quote
  #6 (permalink)  
Old 09-12-09, 15:29
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,534
Code:
SELECT xx.profile
     , l_strike, s_strike
  FROM ( SELECT 'M' AS profile
              , 0 AS code
         UNION ALL
         SELECT 'C',1
         UNION ALL
         SELECT 'A',2
         UNION ALL
         SELECT 'V',3
       ) AS xx
LEFT OUTER
  JOIN ( SELECT MIN(code) AS code, l_strike, s_strike
           FROM (
                /* a bunch of stuff */
                ) AS m
         GROUP
             BY l_strike, s_strike
       ) AS yy
    ON yy.code = xx.code
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #7 (permalink)  
Old 09-12-09, 22:45
moosie moosie is offline
Registered User
 
Join Date: Sep 2009
Posts: 4
Rudy,

This is perfect. Thank you!

Best,
-joe
Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On