nomann@rimfaxe.diku.dk (Ole Nomann Thomsen) (11/07/90)
Hello all. I am doing some programming in informix-sql V2.10, and have run into a problem that I can solve (:-)) , but only inefficiently (:-(). So, if you have the time and energy, please lend me a hand. This is the problem: ==================== I have build a temporary table T1, containing the columns "no" and "lnum" (both integers). The main table contains (among other things) the columns "s_no" (serial) and "l_num" (integer). I need to update the main table, so that the "l_num" is set to the "lnum" from T1 when "no" and "s_no" matches. T1 contains unique "no" to match some of the main table's "s_no" (but not all). Now this statement (repeated from jelly-ware memory) does it: update main set l_num = ( select lnum from T1 {1} where T1.no = main.s_no {1} ) where exists {2} select no from T1 {2} where T1.no = main.s_no; {2} But it's cruciatingly slow: The {1} part of the statement seems to involve searching the entire T1 table, (approx. 500 entries), for each row in main (approx 800). The {2} part seemingly searches T1 *again* but if I leave it out, all the main.l_num with no main.s_no matched by T1.no get updated with NULL. This is catastrophic. A naive estimate (mine :-}) of the involved amount of search follows: {1} for each 800 in main, search the 500 in T1 : 40000 {2} well ... um, the same again : 40000 result : 80000 tests. It certainly seems to take long enough for this, but can it really be the only way to do it ? what if the main table had 10000 rows and T1 8000 ? (shudder!). Both T1 and main's no/ s_no are indexed, which does help, but not nearly enough. Now, what I'd like to see, was a stmt. like this: MERGE (main ordered by s_no), (T1 ordered by no) if main.s_no = T1.no then set main.l_num = T1.lnum; But that's whishfull thinking. Still, can any of you tell me of an efficient way to do this ? I can't seem to find any help in my manual. Please reply by E-mail. Thanks in advance. - Ole. (nomann@diku.dk). "Information is not knowledge" - Frank Zappa.
randall@informix.com (Randall Rhea) (11/08/90)
In article <1990Nov7.115344.27844@diku.dk> nomann@rimfaxe.diku.dk (Ole Nomann Thomsen) writes: >Hello all. I am doing some programming in informix-sql V2.10, and have run >into a problem that I can solve (:-)) , but only inefficiently (:-(). > >Now this statement (repeated from jelly-ware memory) does it: > >update main > set l_num = ( > select lnum from T1 {1} > where T1.no = main.s_no {1} > ) >where exists {2} > select no from T1 {2} > where T1.no = main.s_no; {2} > >But it's cruciatingly slow: Temporary tables can really speed things up in Informix, especially for ACE reports. This will work: SELECT no, lnum FROM T1, main WHERE T1.no = main.s_no INTO TEMP tempmain; UPDATE main SET l_num = (SELECT lnum FROM tempmain WHERE tempmain.no = main.s_no) WHERE s_no IN (SELECT no FROM tempmain); Hopefully, that will be a lot faster. There may be a better way to do it. (without a TEMP table) However, Informix-SQL is a bit limited when it comes to performing an UPDATE while looking up information in more than one table. -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Randall Rhea Informix Software, Inc. Senior Programmer/Analyst, MIS uunet!pyramid!infmx!randall
jfr@locus.com (Jon Rosen) (11/10/90)
In article <1990Nov8.021252.27609@informix.com> randall@informix.com (Randall Rhea) writes: >In article <1990Nov7.115344.27844@diku.dk> nomann@rimfaxe.diku.dk (Ole Nomann Thomsen) writes: >>Hello all. I am doing some programming in informix-sql V2.10, and have run >>into a problem that I can solve (:-)) , but only inefficiently (:-(). >> >>Now this statement (repeated from jelly-ware memory) does it: >> >>update main >> set l_num = ( >> select lnum from T1 {1} >> where T1.no = main.s_no {1} >> ) >>where exists {2} >> select no from T1 {2} >> where T1.no = main.s_no; {2} >> >>But it's cruciatingly slow: > Keep in mind that this SQL is non-standard... There is no way in ANSI SQL or most other mainstream SQLs such as DB2 or RDB to update a column using a Subselect... the ANSI spec (that is ANSI SQL1, not SQL2 or SQL3) requires a value as the right side of an update assignment... In those types of SQLs, the only way to do this is to use either: 1) a single cursor that joins the two tables and then issues regular single row update statements for each row assigning the appropraite value to l_num; or 2) a cursor that retrieves the main table one row and a time, and then issues a singleton Select to get the matching row in the secondary table and does an Update Where Current Of... on each row in the main table; or 3) a cursor that retrieves the main table one row at a time, and a second cursor the retrieves the secondary table one row at a time, each in the same sequence, and do a stepped "join" to find matching rows and update the main table with a Where Current Of... I have done *NOTHING* to test the effectiveness of these solutions... Understand that they require embedded SQL and can not be done from a normal interactive SQL environment... Jon Rosen