21 ноября 2018 г. 3:07

Как использовать поиск "или" в QSqlTableModel для SQLite

QSqlTableModel, Qt, SQLite

Здравствуйте.

У меня есть поле со многими checkBox. При выборе нескольких  checkBox нужно реализовать поиск в SQLite c помощью QSqlTableModel::setSort()  так, чтобы выполнилось условие или тут нашло, или тут, или тут или везде.



Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
30
  • 21 ноября 2018 г. 4:11
  • (ред.)
  • Ответ был помечен как решение.

Вот пример моего кода:

void FindWindow::on_lineEditFind_textChanged(const QString &arg1)
{
    if(arg1.length()>=3){
        filter =QString("ZN LIKE ('%%1%') OR FN LIKE ('%%1%')").arg(arg1);
    } else {
        filter="ZN LIKE ('') OR FN LIKE ('')";
    }
    modelRro->select();
    modelRro->setFilter(filter);
    ui->tableViewRezult->resizeColumnsToContents();
}

При изменении содержимого lineEdit происходит установка фильтра,

Спасибо.

В 4 строчке ZN и FN это названия столбцов?

Да это название столбцов

Что то у меня не работает.

Если делать так, то запрос выполняется

setFilter( "Gender LIKE ('мужчина') ")

а если так, то почему-то не выполняется условие или

setFilter("Name LIKE ('мужчина') OR Gender LIKE ('мужчина') OR PhoneNumber LIKE ('мужчина') ")


Тестируйте запросы в менеджере БД, а потом что все после WHERE используйте как аргумент  setFilter.

Не плохо бы было увидеть саму таблицу и задачу которая вам необходима для установки фильтра


Я проверял названия столбцов.

Вот код бд

PRAGMA foreign_keys = 0;


CREATE TABLE sqlitestudio_temp_table AS SELECT *

FROM SQLliteResumeArray;


DROP TABLE SQLliteResumeArray;


CREATE TABLE SQLliteResumeArray (

NumberID              INTEGER PRIMARY KEY AUTOINCREMENT

NOT NULL

UNIQUE,

Name                  TEXT,

Gender                TEXT,

Age                   INTEGER,

DateOfBirth           DATE,

PhoneNumber           TEXT,

Email                 TEXT,

City                  TEXT,

BusinessTrip          TEXT,

PostDesired           TEXT,

Salary                INTEGER,

CVPost                TEXT,

NameCompany           TEXT,

Experiance            TEXT,

Languages             TEXT,

AdditionalInformation TEXT,

Education             TEXT,

Skills                TEXT,

Comments              TEXT,

Resume                TEXT

);


INSERT INTO SQLliteResumeArray (

NumberID,

Name,

Gender,

Age,

DateOfBirth,

PhoneNumber,

Email,

City,

BusinessTrip,

PostDesired,

Salary,

CVPost,

NameCompany,

Experiance,

Languages,

AdditionalInformation,

Education,

Skills,

Comments,

Resume

)

SELECT NumberID,

Name,

Gender,

Age,

DateOfBirth,

PhoneNumber,

Email,

City,

BusinessTrip,

PostDesired,

Salary,

CVPost,

NameCompany,

Experiance,

Languages,

AdditionalInformation,

Education,

Skills,

Comments,

Resume

FROM sqlitestudio_temp_table;


DROP TABLE sqlitestudio_temp_table;


CREATE INDEX IndexResumeArray ON SQLliteResumeArray (

NumberID,

Name,

Age,

DateOfBirth,

PostDesired,

CVPost,

PhoneNumber,

Email,

City,

Salary,

NameCompany,

Education,

Languages,

Experiance,

Gender,

AdditionalInformation,

Comments,

Resume,

BusinessTrip,

Skills

);


PRAGMA foreign_keys = 1;



Сделал базу по вашей таблице

Запрос работает.

select * from SQLliteResumeArray
where Name LIKE ('мужчина') OR Gender LIKE ('мужчина') OR PhoneNumber LIKE ('мужчина') 

Проверьте в своем менеджере БД, возможно у вас база пустая.

во вложении SQL файл с вашей таблицей. Выполните импорт и пробуйте.



Спасибо.

Извините за беспокойство.

Просто запрос написал с маленькой буквы, а в бд он с большой.


Что бы избежать подобных трудностей я всегда тестирую запросы напрямую а потом уже использую их в Qt

Скажите пожалуйста, как добавить по столбу  с INTEGER поиск от int a; до int b; ?

разобрался, так

SearchTableModel->setFilter(" Age > 30 ");

    SearchTableModel->setFilter(" Age < 35 ");

Еще можно так

SearchTableModel->setFilter("Age BETWEEN 30 AND 35");

Или  так

SearchTableModel->setFilter("Age>=30 AND Age <=35");


Да, ваш вариант правильный, а мой не работал, т.к. оказалось QSqlTableModel запоминает только последний setFilter().

А можно ли сделать сначала один запрос setFilter, а потом искать уже в найденном еще одним setFilter ,и так дальше?

Если не сложно по конкретнее задачу поставьте, на примере таблицы что у вас есть.

Нужно писать вложенные запросы. Или очень сложные фильтры конкретно для QSqlTableModel. Если хотите сохранить предыдущий запрос, то выполняйте это вручную в какую-нибудь переменную.

Ну или создавать временные таблицы в базе данных сырыми запросами, но это ещё сложнее будет.


На примере этой таблицы:

Сначала Age от 30 до 40

Потом Languages Languages LIKE ('Russian%')

Потом Languages City LIKE ('Москва%')

И так дальше. Просто количество фильтров не ограниченно и критерии поиска могут быть разнообразны.

С помощью вложенных запросов врятли получится так написать.

Если в переменную записывать, выйдет слишком громоздко и не оптимально будет идти поиск.

А как это сделать с помощью сложных фильтров QSqlTableModel?




Тогда использовать QSortFilterProxyModel

https://doc.qt.io/qt-5/qtwidgets-itemviews-customsortfiltermodel-example.html

Либо пересмотреть структуру БД, для оптимизации построения запросов.

Похоже что придется создавать временную таблицу.

Новую таблицу нужно создавать через QSqlQuery?

Не знаете, как новой таблице дать данные из setFilter()?



Пытаюсь создать временную таблицу так, но выдает ошибку QSqlError("1", "Unable to execute statement", "no such column: Name")

   QSqlQuery query;
        query.exec("CREATE TEMP TABLE TempTable1 AS SELECT "
           " NumberID           ," 
           "Name                ,"
           "Gender              ,"
           "Age                 ,"
           "DateOfBirth         ,"
           "PhoneNumber         ,"
           "Email               ,"
           "City                ,"
           "BusinessTrip        ,"
           "PostDesired         ,"
           "Salary              ,"
           "CVPost              ,"
           "NameCompany         ,"
           "Experiance          ,"
           "Languages           ,"
           "AdditionalInformation  ,"
           "Education           ,"
           "Skills              ,"
           "Comments            ,"
           "Resume               "
           ";");
        qDebug() << "exec :" << query.lastError();

Если у вас фильтрация таблицы из разных фильтров, то лучше всё-таки попытаться написать фильтр правильно, например

QString strFilter;

if (count > 30)
{
    strFilter.append("count_column > 30");
}
else if (/* ещё какое-нибудь условие*/)
{
    strFilter.append(" AND ");
    strFilter.append("second_column LIKE 'value'");
}

ну и так далее, главное правильно сформировать фильтрующую запись. Это будет формирование более сложного запроса, но это будет всё-таки легче, чем использовать временную таблицу.

Спасибо.

А можно ли сделать поиск не чувствительным к регистру

У вас база данных SQLite?

Как я понимаю, у неё нет встроенных механизмов, поэтому нужно извращаться, например так

select * from mytable where  UPPER(field) like 'AAA';

SQLite из коробки не поддерживает кириллицу в UPPER :-(

То есть, решение из разряда фантастики стандартными средствами для SQLite?

select
  t.test_text
, upper(
    (
        WITH RECURSIVE
        under_name(test_text, char, level) as 
            (select t.test_text, '', 0
            union
            select test_text, coalesce(lu.u,substr(test_text,level,1)), under_name.level+1
            from under_name
            left join (
                select 'А' as u, 'а' as l union select 'Б' as u, 'б' as l union select 'В' as u, 'в' as l union select 'Г' as u, 'г' as l union select 'Д' as u, 'д' as l union select 'Е' as u, 'е' as l union select 'Ё' as u, 'ё' as l union select 'Ж' as u, 'ж' as l union select 'З' as u, 'з' as l union select 'И' as u, 'и' as l union select 'Й' as u, 'й' as l union select 'К' as u, 'к' as l union select 'Л' as u, 'л' as l union select 'М' as u, 'м' as l union select 'Н' as u, 'н' as l union select 'О' as u, 'о' as l union select 'П' as u, 'п' as l union select 'Р' as u, 'р' as l union select 'С' as u, 'с' as l union select 'Т' as u, 'т' as l union select 'У' as u, 'у' as l union select 'Ф' as u, 'ф' as l union select 'Х' as u, 'х' as l union select 'Ц' as u, 'ц' as l union select 'Ч' as u, 'ч' as l union select 'Ш' as u, 'ш' as l union select 'Щ' as u, 'щ' as l union select 'Ь' as u, 'ь' as l union select 'Ы' as u, 'ы' as l union select 'Ъ' as u, 'ъ' as l union select 'Э' as u, 'э' as l union select 'Ю' as u, 'ю' as l union select 'Я' as u, 'я' as l
            ) lu on substr(test_text,level,1)=lu.l
            where level <= length(test_text)
        )
        select group_concat(char,'') from under_name
    )
) upper_text
from
(select 'Съешь ещё этих  мягких французских булок, да выпей же чаю. Test.' test_text) t

мне срочно нужно добавлять на сайт смайлики... фейспалма очень не хватает...

А как такой запрос отразится на скорости поиска?

И скажите пожалуйста, как это решение можно добавить в запрос

TableModel->setFilter(Name LIKE 'Вася');

я думаю, если заменить  SQLite на другую БД, например  postgresql, то можно будет стандартными средствами этот поиск сделать, без таких извращений. И работать будет быстрее точно. Но пока это у вас не является узким местом, то и не замрочивайтесь. Преждевременная оптимизация тоже не нужна.

А вы не знаете, как в  postgresql сделать автозаполнение столбца с ключом?

AUTOINCREMENT

bool DataBase::createTable()
{
    QSqlQuery query;
    if(!query.exec( "CREATE TABLE " TABLE " ("
                            "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                            TABLE_DATE      " DATE            NOT NULL,"
                            TABLE_TIME      " TIME            NOT NULL,"
                            TABLE_RANDOM    " INTEGER         NOT NULL,"
                            TABLE_MESSAGE   " VARCHAR(255)    NOT NULL"
                        " )"
                    )){
        qDebug() << "DataBase: error of create " << TABLE;
        qDebug() << query.lastError().text();
        return false;
    } else {
        return true;
    }
    return false;
}

P/S/ этот ваш последний вопрос уже не имеет прямого отношения к фильтрам в таблице, создавайте, пожалуйста, новые темы для новых вопросов.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Как стать автором?

Внесите вклад в развитие сообщества EVILEG.

Узнайте, как стать автором сайта.

Изучить
Donate

Добрый день, Дорогие Пользователи !!!

Я Евгений Легоцкой, разработчик EVILEG. И это мой хобби-проект, который помогает учиться программированию другим программистам и разработчикам

Если сайт помог вам, и вы хотите также поддержать развитие сайта, то вы можете сделать пожертвование следующими способами

PayPalYandex.Money
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг Timeweb
АС
26 мая 2020 г. 12:29
Артём Сун-Дун-Чан

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50баллов,
  • Очки рейтинга-4
МН
25 мая 2020 г. 12:33
Митя Нагибин

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50баллов,
  • Очки рейтинга-4
f
25 мая 2020 г. 6:05
falcon

C++ - Тест 001. Первая программа и типы данных

  • Результат:66баллов,
  • Очки рейтинга-1
Последние комментарии
28 мая 2020 г. 16:14
Евгений Легоцкой

Qt/C++ - Урок 039. Как закрасить строку в QSqlTableModel по значению в столбце

Ну в моём примере, который в статье сработало так model->setData(model->index(1, 1), 7); Поскольку model->index(1, 0) - это индекс колонки id, которая скрыта, поэтому…
МА
28 мая 2020 г. 16:08
Михаил А

Qt/C++ - Урок 039. Как закрасить строку в QSqlTableModel по значению в столбце

Спасибо, завтра првоерю. А model->setData(model->index(1, 0), 7); Тоже заработало?
28 мая 2020 г. 16:06
Евгений Легоцкой

Qt/C++ - Урок 039. Как закрасить строку в QSqlTableModel по значению в столбце

Да, метод data всё-таки влиял, я переписал его так и заработало удаление QVariant TableModel::data(const QModelIndex &idx, int role) const{ if (role == Qt::BackgroundColorRole) {…
28 мая 2020 г. 15:49
Евгений Легоцкой

Django - Урок 011. Добавление комментариев на сайт с Django

Он более функциональный и его функционал объективно лучше поддерживается Django. Из первого, что приходит на ум: Это наличие полей типа Array Поддержка полей для JSON …
28 мая 2020 г. 15:42
progammist

Django - Урок 011. Добавление комментариев на сайт с Django

а в чем явное преимущество postgresql над mysql?)
Сейчас обсуждают на форуме
RG
28 мая 2020 г. 19:21
Rovshan Gurbanov

Сборка под старые версии Android

У меня SDK почти все версии есть, NDK есть версии 10, 17, 21. Но собирается приложение только с NDK v21 под Android версии 7.0 и выше Версия Qt у меня 5.14.2
28 мая 2020 г. 8:58
Евгений Легоцкой

Освобождение памяти QMainWindow::setCentralWidget

Да, соглашусь. Просто удаление происходит позже, а не сразу.
28 мая 2020 г. 6:43
Михаиллл

При подключении к git как указать пароль?

Нужно сделать ssh-keygen и потом полученый из файла код скопировать в ssh ключ в бикбакете
F
28 мая 2020 г. 2:42
Fidan

QML

Да, проблема ушла, спасибо.
1 мая 2020 г. 9:19
Михаиллл

Как в Qt в qmenu добавить scrollarea

Вот это наследованный класс меню. Но посути это обычное меню. #pragma once#include <QtWidgets>class TransMenu : public QMenu { Q_OBJECTpublic: TransMenu(QWidget* parent = …
О нас
Услуги
© EVILEG 2015-2020
Рекомендует хостинг TIMEWEB