Ouch, I certainly did forget the where clauses!

Table1 and Table2 are going to be roughly the same size.
What I am trying to do, btw, is to take an extract from a prior period, which 
has had the "Value" added to it, and move that value in to the matching record 
in the new extract. There is a natural key in the table that is being 
extracted, but the columns that make up that natural key are not exposed to us 
mere mortals. Of the fields I have to play with, only key1 is actually part of 
the natural key in the source table. The others are fields which could be 
freely changed from one month to another. The higher the key number, the most 
likely it is to be changed from one month to another.

In your selects below, lets say we have two records in table2 which have 
exactly the same keys as a record in Table1, won't the select then spit out two 
values in the select? Or am I missing how that case is excluded?

And should I take it the two last Left joins should have been Level2 and 
Level1, and not repeat the use of Level4 and Level5?

And your option (a) is only one of 5 selects, each having one less key?


For (b), lets say:

Table1
Rowid|Key1 | Key2 | Key3 | Key4 | Key5
1         1          2         3         4         5

Table2
Rowid|Key1 | Key2 | Key3 | Key4 | Key5|Value
11        1         2         3         4         5         x

12        1         2         3         4       -5          y

Just  looking at levels 4 and 5 wouldn't the results be...

Table1.Rowid |   Level5.Rowid  | Level4.Rowid |  Value

1                         11                    12                        x    
(from level 5)1                         null                    11              
         y    (from level 4)
1                         null                    12                       y    
(from level 4)


Or am I mis-interpreting what you wrote?

Um, I am wrong, cause I just tried it and sqlite only returns the level 5 
result. I have no clue why!

David


________________________________
 From: Petite Abeille <petite.abei...@gmail.com>
To: General Discussion of SQLite Database <sqlite-users@sqlite.org> 
Sent: Monday, March 11, 2013 3:24 PM
Subject: Re: [sqlite] Fuzzy joins
 

On Mar 11, 2013, at 4:54 PM, David Bicking <dbic...@yahoo.com> wrote:

> Am I missing an obviously better way to do it? 
> A way that can easily be expanded when they come back to me and say if I 
> looked at a fifth column, you'd have been able to match it….

As they stand, your updates will always match whatever was computed last as you 
don't have a where clause in your update statements. Most likely not what you 
want.

If only SQLite had a merge statement, this would all be much easier.

Anyhow, personally, I would decompose the problem into two steps: 


(1) How to join Table1 to Table2 considering these various keys.
(2) How to update Table2 with Table2's value given (1)


For (1), you have two main options: (a) keys concatenation  or (b) a series of 
left joins 


(warning: pseudo code ahead)


(a)

select    Table1.row_id as t1_row_id,
          Table2.value
from      (
            select  rowid as row_id,
                    key1 || '.' || key2 || '.' || key3 || '.' || key4 || '.' || 
key5 as key
            from    Table1
          )
as        Table1

left join (
            select  rowid as row_id,
                    key1 || '.' || key2 || '.' || key3 || '.' || key4 || '.' || 
key5 as key,
                    value
            from    Table2
          )
as        Table2
on        Table2.key = Table1.key

The above will always result in two full table scan.


(b) 

select    Table1.rowid as t1_row_id,
          coalesce( Level5.value, Level4.value, Level3.value, Level2.value, 
Level1.value ) as value
from      Table1

left join Table2
as        Level5
on        Level5.key1 = Table1.key1
and       Level5.key2 = Table1.key2
and       Level5.key3 = Table1.key3
and       Level5.key4 = Table1.key4
and       Level5.key5 = Table1.key5

left join Table2
as        Level4
on        Level4.key1 = Table1.key1
and       Level4.key2 = Table1.key2
and       Level4.key3 = Table1.key3
and       Level4.key4 = Table1.key4
and       Level5.key1 is null

left join Table2
as        Level3
on        Level3.key1 = Table1.key1
and       Level3.key2 = Table1.key2
and       Level3.key3 = Table1.key3
and       Level4.key1 is null

left join Table2
as        Level4
on        Level4.key1 = Table1.key1
and       Level4.key2 = Table1.key2
and       Level3.key1 is null

left join Table2
as        Level5
on        Level5.key1 = Table1.key1
and       Level4.key1 is null


While the second option looks more verbose, it may be more appropriate if 
Table2 is small in relation to Table1, and Table1 can be pruned by key1 at the 
very least.


(2) Once you have the data joined, the update itself is much more 
straightforward. Wrap one of the select as a 'create temporary table t2t as' 
and use that in the update statement:

update  Table1
set     value = ( select value from t2t where t2t.row_id = Table1.rowid )

where   exists
        (
          select  1
          from    t2t
          where   t2t.row_id = Table1.rowid
        )


As always, YMMV.



_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to