简体   繁体   中英

How can I join 3 tables (or sub-select) in SQLite?

I have a table called searches which has an id and a table of positive and negative which are associated with a search_id and has a word (ie: "some positive word" or "some negative word".

I'm trying to do this all in one query (not sure if its possible): I want to get a list of searches where the search does not contain any of the negative words in the list and DOES include any of the positive words in the list.

The basic idea is given a search id (i'm trying to find related searches)...get this search ids positve and negative words, and then select all other searches where their positive words match (any one or more words) and does NOT match any of the negative words.


    const positive = await db.queryEntries(
      `SELECT * FROM positive WHERE search_id = ?`,
      [search_id]
    );
    const negative = await db.queryEntries(
      `SELECT * FROM negative WHERE search_id = ?`,
      [search_id]
    );
    console.log("positive: ", positive, " negative: ", negative);
    let pIn = "";
    let nIn = "";
    positive.forEach((p, i) => {
      pIn += "?" + (i < positive.length - 1 ? "," : "");
    });

    negative.forEach((n, i) => {
      nIn += "?" + (i < negative.length - 1 ? "," : "");
    });
    console.log("pIn", pIn);
    const pWords = <[]>positive.map((p) => p.word);
    const nWords = <[]>negative.map((n) => n.word);
    console.log("pWords", pWords);
    const args = [].concat(pWords, nWords);
    console.log("args", args);
    /*
           INNER JOIN positive pos ON pos.search_id = s.id
       INNER JOIN negative neg ON neg.search_id = s.id

       */
    const searches = await db.queryEntries(
      `SELECT s.* FROM searches s, positive p, negative n
      INNER JOIN positive ON s.id = positive.search_id
      INNER JOIN negative ON s.id = negative.search_id
       WHERE p.word IN (${pIn}) AND p.word NOT IN (${nIn})
       `,
      args
    );

    console.log("searches: ", searches.length);

I've tried so many things now and I keep getting thousands of rows and there should be only 3 searches that match

Here are some queries:

sqlite> .schema positive
CREATE TABLE positive (
                                id string PRIMARY KEY,
                                search_id STRING NOT NULL,
                                word string NOT NULL);
sqlite> select * from positive where word = 'css';
a63303ca-7b07-49d8-a500-fa3e48c6657d|e428da2f-334d-4444-8b78-719480393112|css
32da7a93-8aea-493a-bd55-e99eacc40d92|621882c3-db65-47a4-bd0d-fc39ed09aabe|css
f805c86f-9436-40d8-8b26-0639bdb8d06d|3779ba1b-9b42-43d1-9133-e5622176ce83|css
sqlite> select * from positive where word = 'css';
a63303ca-7b07-49d8-a500-fa3e48c6657d|e428da2f-334d-4444-8b78-719480393112|css
32da7a93-8aea-493a-bd55-e99eacc40d92|621882c3-db65-47a4-bd0d-fc39ed09aabe|css
f805c86f-9436-40d8-8b26-0639bdb8d06d|3779ba1b-9b42-43d1-9133-e5622176ce83|css
sqlite> select * from negative where word = 'css';
sqlite> select * from searches LIMIT 1;
326f3d15-97cd-4da9-bd82-a1578ac8e15f|1535d3e5-cb05-4514-81c8-4fa787e52e53|svelte|2021-11-01T08:10:10.982Z|2022-02-20T03:10:42.128Z|job
sqlite> 
sqlite> .schema searches
CREATE TABLE searches (
                                id STRING PRIMARY KEY,
                                user_id STRING NOT NULL,
                                name STRING NOT NULL,
                                created_at TEXT,
                                updated_at TEXT
                        , type TEXT DEFAULT 'job');

so for example if the requested search has 'css' as a positive word and 'angular' as a negative word, I want all searches that have css as a positive word and DO NOT have angular as a postitive word.

You can use EXISTS and NOT EXISTS to check if the words exist or not in the 2 tables:

SELECT s.*
FROM searches s
WHERE EXISTS (SELECT 1 FROM positive p WHERE p.word IN ('css', ... ) AND p.search_id = s.id)
  AND NOT EXISTS (SELCT 1 FROM negative n WHERE n.word IN ('angular', ... ) AND n.search_id = s.id);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM