sqlsqlite

How to select record matching all parameters?


I have a table catalog_view. I contains contacts with assigned categories. Contacts can have several categories. I want to select contacts, which belong to all categories selected by the user.

e.g. contact "Jone" belongs to categories [1,2,3,4,5,6] and contact "Jay" belongs to categories [1,3]. If user select categories [2,3], only "Jone" should be returned, if [1]|[3]|[1,3] selected, both should be returned, if [7]|[1,7] selected, none should be returned.

How should I build query and/or change tables to achieve it?

query which selects contacts by single category

SELECT * FROM catalog_view WHERE (category_id = ?)

this query selects record if assigned categories matches any of those and returns number of contacts rows up to quantity of parameters, also they are not force celection to all of them.

SELECT * FROM catalog_view WHERE (category_id = ? OR category_id = ? OR category_id =?)

this query always returns an empty table, as row in current template for catalog_view has only one category_id

SELECT * FROM catalog_view WHERE (category_id = ? AND category_id = ? AND category_id =?)

contacts

CREATE TABLE IF NOT EXISTS contacts_table (
    _id integer primary key,
    title text default '',
    title_lower text default '',
    title_short text default '',
    photo blob, number text default '',
    note text default '',
    note_lower text default '',
    email text, partner int default '0',
    contact_id int default '0',
    current_user text default '',
    categories text default '',
    saved integer default '0'
);

categories

CREATE TABLE IF NOT EXISTS categories_table (
    _id integer primary key,
    category_id integer,
    parent_id integer,
    name text,
    section_name text,
    current_user text,
    sub_name text default ''
);

contacts with categories

CREATE TABLE IF NOT EXISTS contacts_categories_table (
    _id integer primary key,
    contact_id integer,
    category_id integer,
    current_user text
);

catalog view contacts

CREATE VIEW IF NOT EXISTS catalog_view AS
SELECT contacts_table._id AS _id,
       contacts_table.contact_id,
       contacts_table.title_lower,
       contacts_table.note_lower,
       contacts_table.current_user,
       contacts_table.saved,
       contacts_table.partner,
       contacts_table.title,
       contacts_table.email,
       contacts_table.title_short,
       contacts_table.number,
       contacts_table.note,
       contacts_table.categories,
       categories_table.section_name,
       contacts_table.contact_id,
       categories_table.parent_id,
       categories_table.category_id
FROM contacts_categories_table
         INNER JOIN contacts_table ON (contacts_categories_table.contact_id = contacts_table.contact_id AND
                                       contacts_categories_table.current_user = contacts_table.current_user)
         LEFT OUTER JOIN categories_table ON (contacts_categories_table.category_id = categories_table.category_id AND
                                              contacts_categories_table.current_user = categories_table.current_user) 

Solution

  • You can try something like:

    SELECT distinct name from catalog_view s
    where NUMBER_OF_CONTACT_SELECTION =
          (SELECT count(*) from catalog_view t
          where t.name = s.name and
          category_id in(YOUR CONTACT SELECTION HERE IN FORMAT OF 1,3,4...)) 
    

    so for 1,3 your query should be:

    SELECT distinct name from catalog_view s
    where 2 =
          (SELECT count(*) from catalog_view t
          where t.name = s.name and
          category_id in(1,3)) 
    

    for 1,2,4,7 it should be -> 4 = (.....IN(1,2,4,7))