Russian Qt Forum

Qt => Базы данных => Тема начата: CL0NE от Сентябрь 27, 2010, 22:24



Название: [Решено] SQL + Model + Tree?
Отправлено: CL0NE от Сентябрь 27, 2010, 22:24
Дано:
база данных с несколькими двумя таблицами вида
A
id
id_b
text
B
id
parent
text

Что нужно получить:
дерево, являющееся обьединением этих двух таблиц
[-]Text A 1
[-]Text B 1
[-]Text B 2
[-]Text B 3
[-]Text A 2
[-]Text B 4
...

Вариации:
а) Извлечь через QSqlQuery данные и вручную заполнить  QStandardItemModel или даже QTreeWidget (здесь вроде бы вопросов у меня не возникает, но решение кажется несколько корявым что ли)
б) Писать свою QSqlTreeModel.
в) Написать свою proxy-модель (найдено как совет на аналогичный вопрос гуглом)

Суть вопроса:
Нужна помощь знающих людей в том как это реализовать и какие есть еще вариации. Я вовсе не прошу, чтобы за меня это кто-то сделал, мне всего лишь нужен толчок в нужную сторону..


Название: Re: SQL + Model + Tree?
Отправлено: crossly от Сентябрь 27, 2010, 22:55
поиск тебе под зад... :) (сори за возможно не уместный юмор)... но на самом деле... тема на этом форуме уже десяток раз подымалась... :)


Название: Re: SQL + Model + Tree?
Отправлено: CL0NE от Сентябрь 27, 2010, 23:19
Тут еще загвоздка, как цеплять выборку из первой таблицы к другой, ведь данные там различаются (потому и две таблицы)

зы. хотя возможно поторопился с созданием темы...


Название: Re: SQL + Model + Tree?
Отправлено: CroCIV от Сентябрь 28, 2010, 07:19
А зачем тебе id_b в таблице А?


Название: Re: SQL + Model + Tree?
Отправлено: CroCIV от Сентябрь 28, 2010, 07:48
Например вот так.. дерево будет строиться по частям по мере необходимости новой ветки...
Не компилировал, возможны дуратские ошибки
Код:
void <НазваниеТвоегоКласса>::<НазваниеТвоегоСлота1>() //думаю это будет слот, чтоб была возможность обновлять дерево (вдруг у тебя программа будет многопользовательская)
{
disconnect(ui.treeWidget,SIGNAL(itemExpanded(QTreeWidgetItem *)),this,SLOT(<НазваниеТвоегоСлота2>(QTreeWidgetItem *)));
ui.treeWidget->clear();
QSqlQueryModel *sql = new QSqlQueryModel(this);
sql->setQuery("select distinct text, id_b, id from A order by text",QSqlDatabase::database());
if (sql->lastError().isValid())
QMessageBox::warning(this, "Соединение с SQL-сервером","Обнаружена ошибка соединения:\n"+sql->lastError().text(),QMessageBox::Ok);
else
{
ui.treeWidget->setColumnCount(3);
ui.treeWidget->setColumnHidden(1,true);
ui.treeWidget->setColumnHidden(2,true);
QStringList sl;
sl<<"Название"<<"PKeyB"<<"PKeyA";
ui.treeWidget->setHeaderLabels(sl);
for (int j=0; j<sql->rowCount(); j++)
{
QTreeWidgetItem *twihead = new QTreeWidgetItem(ui.treeWidget);
for (int i=0; i<ui.treeWidget->columnCount(); i++)
{
twihead->setText(i, sql->record(j).value(i).toString());
if (!twihead->text(1).isEmpty())
twihead->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
}
}
}
for (int i=0; i<ui.treeWidget->columnCount(); i++)
ui.treeWidget->resizeColumnToContents(i);
connect(ui.treeWidget,SIGNAL(itemExpanded(QTreeWidgetItem *)),this,SLOT(<НазваниеТвоегоСлота2>(QTreeWidgetItem *)));
}

Код:
void <НазваниеТвоегоКласса>::<НазваниеТвоегоСлота2>(QTreeWidgetItem *twi)
{
if (twi->childCount()==0)
{
QSqlQueryModel *sql = new QSqlQueryModel(this);
sql->setQuery("select distinct t1.text, t1.id, case when t2.id is null then '0' else '1' end from B t1 left join B t2 on t2.parent = t1.id where t1.parent = "+twi->text(1)+" order by t1.text",QSqlDatabase::database());
if (sql->lastError().isValid())
QMessageBox::warning(this, "Соединение с SQL-сервером","Обнаружена ошибка соединения:\n"+sql->lastError().text(),QMessageBox::Ok);
else
{
for (int i=0; i<sql->rowCount(); i++)
{
QTreeWidgetItem *twic = new QTreeWidgetItem(twi);
for (int j=0; j<2; j++)
twic->setText(j, sql->record(i).value(j).toString());
if (sql->record(i).value(2).toBool())
twic->setChildIndicatorPolicy (QTreeWidgetItem::ShowIndicator);
}
}
}
ui.treeWidget->resizeColumnToContents(0);
}


Название: Re: SQL + Model + Tree?
Отправлено: Karl-Philipp от Сентябрь 28, 2010, 12:23
>>Толчок в нужную сторону
http://qt-apps.org/content/show.php/QyurSqlTreeView?content=114372
+ поиск по форуму: тема не единажды подымалась и были конкретные решения.


Название: Re: SQL + Model + Tree?
Отправлено: CL0NE от Сентябрь 28, 2010, 18:06
А зачем тебе id_b в таблице А?
Как я написал уже выше, таблицы различаются (просто приведенный пример - упрощен, т.к. не существенно), но единственная связь - тот самый id_b, и нужно, используя данную связь, отобразить соответствующую иерархию :)

А пока что я задействовал поиск и открыто с десяток вкладок, надо бы перечитать все :) Ежели окажусь слишком туп - буду дальше донимать вопросами в этой теме ^^


Название: Re: SQL + Model + Tree?
Отправлено: CroCIV от Сентябрь 29, 2010, 08:39
Как я написал уже выше, таблицы различаются (просто приведенный пример - упрощен, т.к. не существенно), но единственная связь - тот самый id_b, и нужно, используя данную связь, отобразить соответствующую иерархию :)

тогда тут три варианта: либо А.id не будет уникальным, либо у каждого А.id может быть только по одному потомку, либо нужно создавать таблицу АВ с полями id_a и id_b, которая свяжет множество потомков таблицы В с одной записью таблицы А.

Щас пример свой поправлю для случая, когда А.id является уникальным, а единственный потомок этой записи указан в поле A.id_b

Попробуй разобраться с этим примером он как раз под твою предметную область адаптирован


Название: Re: SQL + Model + Tree?
Отправлено: CL0NE от Сентябрь 29, 2010, 22:01
Цитировать
у каждого А.id может быть только по одному потомку
именно
Цитировать
пробуй разобраться с этим примером он как раз под твою предметную область адаптирован
спасибо, курим пока потихоньку все, что насобирали:)


Название: Re: SQL + Model + Tree?
Отправлено: RedDog от Сентябрь 29, 2010, 23:10
Вот тут (http://forum.codenet.ru/showpost.php?p=245743&postcount=4) мой алгоритм составления дерева из БД. Работает очень шустро, и требуется всего один запрос к БД в самом начале. Можно на его основе заполнять модель, которую потом привязывать к TreeView, т.е. заточить под MVC


Название: Re: SQL + Model + Tree?
Отправлено: CroCIV от Октябрь 01, 2010, 13:01
Вот тут (http://forum.codenet.ru/showpost.php?p=245743&postcount=4) мой алгоритм составления дерева из БД. Работает очень шустро, и требуется всего один запрос к БД в самом начале. Можно на его основе заполнять модель, которую потом привязывать к TreeView, т.е. заточить под MVC

а если у вас таблица имеет, скажем, "стопитьсот" записей, а мне нужно только одну вершинку второго уровня? а если у вас "стопитьсот" пользователей подключаются к вашей бд и все делают
SELECT * FROM nodes ORDER BY parentid по "стапитьсот" записям, и всем нужно только по одной вершинке первого-второго уровня?  ::)


Название: Re: SQL + Model + Tree?
Отправлено: RedDog от Октябрь 01, 2010, 14:45
а если у вас таблица имеет, скажем, "стопитьсот" записей, а мне нужно только одну вершинку второго уровня? а если у вас "стопитьсот" пользователей подключаются к вашей бд и все делают
SELECT * FROM nodes ORDER BY parentid по "стапитьсот" записям, и всем нужно только по одной вершинке первого-второго уровня?  ::)
в очень многопользовательском режиме не тестил, но 10-20 юзеров работали с количеством ~ 100 тыс. записей, нагрузка на сервер незначительная, да и вопрос тогда стоял в том что бы как можно быстрее нарисовать полное дерево. С рекурсией это было в десятки раз дольше и нагрузка на сервер возрастала.


Название: Re: SQL + Model + Tree?
Отправлено: CL0NE от Октябрь 05, 2010, 23:20
Если кому интересно:
После продолжительного чтения форума/документации, от использования TreeWidget/StandardItemModel я отказался и выбрал второй пункт - своя модель.
Основная идея реализации получилась похожей на реализацию Sergeich'a, в результате используется измененный под свои нужды код из сообщения http://www.prog.org.ru/index.php?topic=8028.msg42804#msg42804

Всем огромное спасибо :)