On Wednesday, 2 January, 2019 16:58, Jonathan Moules 
<jonathan-li...@lightpear.com> wrote:

>Gah, sorry. Another typo. I really should be more awake when I post
>to this list. The non-simplified code does have the item_id on the
>subquery (otherwise it simply wouldn't execute at all of course). So:

>SELECT *
>   FROM item_info
>   JOIN (
>     select
>       count(1) as num,
>       item_id
>     from users
>     group by item_id)
>  USING (item_id)
>  where item_id = ?;

Now perhaps we are getting somewhere.  So now what exactly is your complaint?  
You have asked for the following join to occur:

JOIN this table, which you can see by the following command:
  select * from item_info
with the table that you can see by the following command:
  select count(1) as num, item_id from users group by item_id
using the common column item_id in both tables
and then to return only the row where the item_id is the specific one provided.

So, the ONLY way to solve this is to generate the table on the RHS of the join 
first, and then join it to the item_info table, and then return only the row 
you have asked for.  This produces the following plan:

CREATE TABLE users (
     item_id   TEXT REFERENCES item_info (item_id)
                       NOT NULL
                       COLLATE NOCASE,
     some_data     TEXT
);

CREATE INDEX users__item_id__idx ON users (
     item_id
);

CREATE TABLE item_info (
     item_id   TEXT PRIMARY KEY ON CONFLICT IGNORE
                       NOT NULL
                       COLLATE NOCASE,
     more_data     TEXT
);
.eqp full
SELECT *
   FROM item_info
   JOIN (
     select
       count(1) as num,
       item_id
     from users
     group by item_id)
  USING (item_id)
  where item_id = ?;
QUERY PLAN
|--MATERIALIZE 1
|  `--SCAN TABLE users USING COVERING INDEX users__item_id__idx (~1048576 rows)
|--SEARCH TABLE item_info USING INDEX sqlite_autoindex_item_info_1 (item_id=?) 
(~1 row)
`--SCAN SUBQUERY 1 (~96 rows)
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     77    0                    00  Start at 77
1     Integer        45    1     0                    00  r[1]=45
2     Once           0     45    0                    00  materialize 
"subquery_1"
3     OpenEphemeral  1     2     0                    00  nColumn=2
4     Noop           3     1     0                    00
5     Integer        0     5     0                    00  r[5]=0; clear abort 
flag
6     Null           0     8     8                    00  r[8..8]=NULL
7     Gosub          7     42    0                    00
8     OpenRead       4     3     0     k(2,NOCASE,)   00  root=3 iDb=0; 
users__item_id__idx
9     ColumnsUsed    4     0     0     1              00
10    Explain        10    0     0     SCAN TABLE users USING COVERING INDEX 
users__item_id__idx (~1048576 rows)  00
11    Noop           0     0     0                    00  Begin WHERE-loop0: 
users
12    Rewind         4     28    10    0              00
13      Noop           0     0     0                    00  Begin WHERE-core
14      Column         4     0     9                    00  r[9]=users.item_id
15      Compare        8     9     1     k(1,NOCASE)    00  r[8] <-> r[9]
16      Jump           17    21    17                   00
17      Move           9     8     1                    00  r[8]=r[9]
18      Gosub          6     33    0                    00  output one row
19      IfPos          5     45    0                    00  if r[5]>0 then 
r[5]-=0, goto 45; check abort flag
20      Gosub          7     42    0                    00  reset accumulator
21      Integer        1     10    0                    00  r[10]=1
22      AggStep        0     10    2     count(1)       01  accum=r[2] 
step(r[10])
23      If             4     25    0                    00
24      Column         4     0     3                    00  r[3]=users.item_id
25      Integer        1     4     0                    00  r[4]=1; indicate 
data in accumulator
26      Noop           0     0     0                    00  End WHERE-core
27    Next           4     13    0                    01
28    Noop           0     0     0                    00  End WHERE-loop0: users
29    Gosub          6     33    0                    00  output final row
30    Goto           0     45    0                    00
31    Integer        1     5     0                    00  r[5]=1; set abort flag
32    Return         6     0     0                    00
33    IfPos          4     35    0                    00  if r[4]>0 then 
r[4]-=0, goto 35; Groupby result generator entry point
34    Return         6     0     0                    00
35    AggFinal       2     1     0     count(1)       00  accum=r[2] N=1
36    SCopy          2     11    0                    00  r[11]=r[2]
37    SCopy          3     12    0                    00  r[12]=r[3]
38    MakeRecord     11    2     10                   00  r[10]=mkrec(r[11..12])
39    NewRowid       1     13    0                    00  r[13]=rowid
40    Insert         1     10    13                   08  intkey=r[13] 
data=r[10]
41    Return         6     0     0                    00  end groupby result 
generator
42    Null           0     2     3                    00  r[2..3]=NULL
43    Integer        0     4     0                    00  r[4]=0; indicate 
accumulator empty
44    Return         7     0     0                    00
45    Return         1     0     0                    00  end subquery_1
46    OpenRead       0     4     0     2              02  root=4 iDb=0; 
item_info
47    ColumnsUsed    0     0     0     3              00
48    OpenRead       5     5     0     k(1,NOCASE)    02  root=5 iDb=0; 
sqlite_autoindex_item_info_1
49    ColumnsUsed    5     0     0     1              00
50    Explain        50    0     0     SEARCH TABLE item_info USING INDEX 
sqlite_autoindex_item_info_1 (item_id=?) (~1 row)  00
51    Noop           0     0     0                    00  Begin WHERE-loop0: 
item_info
52    CursorHint     5     0     0     EQ(c0,expr)    00
53    Variable       1     14    0                    00  r[14]=parameter(1,)
54    IsNull         14    75    0                    00  if r[14]==NULL goto 75
55    Affinity       14    1     0     B              00  affinity(r[14])
56    SeekGE         5     75    14    1              00  key=r[14]
57    IdxGT          5     75    14    1              00  key=r[14]
58    DeferredSeek   5     0     0                    00  Move 0 to 5.rowid if 
needed
59    Explain        59    0     0     SCAN SUBQUERY 1 (~96 rows)  00
60    Noop           0     0     0                    00  Begin WHERE-loop1: 
subquery_1
61    Column         5     0     15                   00  
r[15]=item_info.item_id
62    CursorHint     1     0     0     EQ(r[15],c1)   00
63    Rewind         1     75    0                    00
64      Column         5     0     16                   00  
r[16]=item_info.item_id
65      Column         1     1     17                   00  
r[17]=subquery_1.item_id
66      Ne             17    73    16    (NOCASE)       51  if r[16]!=r[17] 
goto 73
67      Noop           0     0     0                    00  Begin WHERE-core
68      Column         5     0     18                   00  
r[18]=item_info.item_id
69      Column         0     1     19                   00  
r[19]=item_info.more_data
70      Column         1     0     20                   00  r[20]=subquery_1.num
71      ResultRow      18    3     0                    00  output=r[18..20]
72      Noop           0     0     0                    00  End WHERE-core
73    Next           1     64    0                    01
74    Noop           0     0     0                    00  End WHERE-loop1: 
subquery_1
75    Noop           0     0     0                    00  End WHERE-loop0: 
item_info
76    Halt           0     0     0                    00
77    Transaction    0     0     3     0              01  usesStmtJournal=0
78    Goto           0     1     0                    00

Which does exactly what you asked in the most efficient manner possible.

What is it that you think it ought to be doing instead?

---
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.





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

Reply via email to