Russian Qt Forum

Qt => Базы данных => Тема начата: ammaximus от Июль 29, 2014, 20:10



Название: Структура бд
Отправлено: ammaximus от Июль 29, 2014, 20:10
Задача такая в таблице основной параметр время, этот столбец всегда есть, он используется как уникальный ид.
Во время работы приходят пачки вида (время,название параметра,значение параметра). Если время совпадает - это одна строка. Нужно все это накапливать, а впоследствии делать запросы, получая простую таблицу где первый столбец время, а остальные те которые приходили. Также должно быть можно получить заголовки этих самых названий параметров. У меня получилась реализация с использованием alter table add column, но мне кажется это что то не то. Сейчас думаю в сторону двойного ключа, где первый столбец время, второй название параметра, а далее уже значения. Тут непонятно как сделать из этого выборку, придется много раз запрашивать.
Попробовал контейнеры, получилось treemap(time,hashmap<name,value>)  + отдельный массив уникальных name.
1. Как сделать бд
2. Как сделать контейнерами
P.s. sqlite


Название: Re: Структура бд
Отправлено: кып от Июль 31, 2014, 15:25
Не совсем понял, но посмотрите EAV модель данных.


Название: Re: Структура бд
Отправлено: ammaximus от Август 01, 2014, 19:20
Возможно плохо объяснил, разрешите попробовать снова.

Допустим в доме есть контроллер климата. К нему может быть подключены разные термометры, барометры, и т.д. Изначально база имеет вид
Код:
Время

В определенный момент времени издается сигнал на выполнение измерений - поскольку все датчики работают асинхронно они ответят в разное время, но ответ в пределах одной минуты для меня считается одновременным, поэтому я заранее сохраняю время выдачи сигнала и подставляю его.

Мне приходит ответ в такой форме
Код:
Термометр, 36.6
, я добавляю время, получается
Код:
10:43, Термометр, 36.6
БД должна быть хранить следующее:
Код:
Время Термометр
10:43 36.6

Проблема следующая - до выдачи сигнала мне неизвестно включен ли сейчас термометр, а также вообще что включено и т.д. Пользователь имеет право в любой момент добавить новое устройство, но в бд данные должны попадать только с того момента, как устройство прислало ответ. Необходима возможность удалять строки, более того если в столбце нет ни одного значения (все null) столбец более не нужен. Запросы к таблице должны возвращать мне такую выборку:
Код:
Время Термометр Барометр
10:43 36.6 null
10:48 36.7 180

Как то не довелось работать с БД ранее, вопрос вроде должен быть простой, из разряда как правильно организовать связь таблиц и запрашивать к ним. Я пока сделал в лоб - с помощью одной таблицы и ALTER TABLE ADD COLUMN. Но мне кажется, что можно как то сделать через связанные таблицы.


Название: Re: Структура бд
Отправлено: Пантер от Август 04, 2014, 07:26
А как тебе такой вариант:

TimeDeviceValue
10:43barometer100
10:48thermometer180
10:48barometer120


Название: Re: Структура бд
Отправлено: ammaximus от Август 04, 2014, 11:26
Думал об этом, а как сделать запрос к этой таблице, чтобы получить результат в той форме как я писал и не будет ли это слишком долго?


Название: Re: Структура бд
Отправлено: Пантер от Август 04, 2014, 11:37
Про результат немного не понял - повтори.


Название: Re: Структура бд
Отправлено: ammaximus от Август 04, 2014, 12:06

Запросы к таблице должны возвращать мне такую выборку:
Код:
Время Термометр Барометр
10:43 36.6 null
10:48 36.7 180


Название: Re: Структура бд
Отправлено: Пантер от Август 04, 2014, 12:08
А зачем выборка такого плана? Объясни ее суть.


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 12:16
Я не силён в БД, но обычный group by, разве не подойдёт?


Название: Re: Структура бд
Отправлено: Bepec от Август 04, 2014, 12:17
Ну если со стороны быстро взглянуть - вам просто 2 таблицы нужны. Барометра и Термометра.
Код:
Таблица baro
time  Value.
Таблица termo
Time Value.

А потом делать выборку типа такой
Псевдокод!!!
Код:
Select baro.Time, baro.Value, termo.Value from baro, termo where baro.time = termp.time;
Тут не учитывается вариант что данные об одном времени отсутствуют в одной из таблиц. Но это я не помню как по условиям ставится :/


Название: Re: Структура бд
Отправлено: Пантер от Август 04, 2014, 12:21
Bepec, не канает, у него могут подключаться новые девайсы.


Название: Re: Структура бд
Отправлено: Bepec от Август 04, 2014, 12:26
Не канает по причине что параметров может быть больше 2 и запрос придётся менять. Но универсализма тут мы не добьёмся на мой взгляд.
Сделать по таблице на каждый вид параметра и потом поступить как предлагает  __Heaven__ - а именно
Код:
select * from baro, termo, hermo group by time

PS ххы, а ведь и получается универсализм. Если бд позволяет получить список таблиц, запрос мы можем сформировать динамически и в результате по идее получаем нужную нам выборку из N таблиц/параметров.


Название: Re: Структура бд
Отправлено: ammaximus от Август 04, 2014, 12:26
А зачем выборка такого плана? Объясни ее суть.
Эти данные я планирую записать в файл формата csv.
Цитировать
Я не силён в БД, но обычный group by, разве не подойдёт?
Может и так, но у меня не получилось.

Цитировать
Ну если со стороны быстро взглянуть - вам просто 2 таблицы нужны. Барометра и Термометра.

Понадобится N таблиц, т.к. девайсов может быть много. Решение с созданием таблиц ничем не лучше alter table.


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 12:31
Если устройства могут добавляться, то:
1) сначала базу можно опросить на уникальность устройств
2) Сделать запрос для каждого устройства, при этом в заголовке колонки можно записать его имя
3) Объединить таблицы по колонке время.

2 и 3 имею в виду, что нужно написать в одном запросе


Название: Re: Структура бд
Отправлено: Пантер от Август 04, 2014, 12:32
Получить список таблиц - костыльно.


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 12:32
Тьфу. Не про добавление устройства говорил, а про требуемый вид таблицы ответа на запрос


Название: Re: Структура бд
Отправлено: ammaximus от Август 04, 2014, 12:41
Если устройства могут добавляться, то:
1) сначала базу можно опросить на уникальность устройств
2) Сделать запрос для каждого устройства, при этом в заголовке колонки можно записать его имя
3) Объединить таблицы по колонке время.

2 и 3 имею в виду, что нужно написать в одном запросе

Код:
Cursor c = sqlExec("SELECT time DISTINCT(time) FROM mainTable ");
while(c.hasNext()){
sqlExec("SELECT * FROM mainTable WHERE device = c.device" GROUP BY time)
}

Как одним запросом то?


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 13:06
Как одним запросом то?

Повторюсь, что плохо знаком с БД. Работал давно. БД и Qt ни разу не пробовал, но всё же попытаюсь (как бы я сделал в Access VBA):
База имеет вид, как предложил Пантер.
А как тебе такой вариант:

TimeDeviceValue
10:43barometer100
10:48thermometer180
10:48barometer120

1) запрашиваем все уникальные Device (надеюсь, знаете, как сделать), получили QStringList devices девайсов
2) создаём некий QString query и пошли создавать запрос:

Код:
query = "SELECT timeTbl.Time AS [TIME], ";
for (int i = 0; i < devices.size(); ++i)        //использовать лучше foreach
{
    query += QString("device%1.Value AS [%2], ").arg(i).arg(devices.at(i))
}

Таким образом мы поименовали колонки на нужные. Теперь нужно выбрать строки   (запятую, которая получилась на конце нужно стереть)
Код:
query += "FROM mainTable as timeTbl "

Сейчас мы пока что выводим только время из главной таблицы. Присоединяем каждое устройство:
Код:
for (int i = 0; i < devices.size(); ++i)
{
    QString subQuery ("SELECT Time, Value From mainTable WHERE Device = %1").arg(devices.at(i))
    query += QString("LEFT JOIN (%1) AS device%2 ON  (timeTbl.Time= device%2.Time) ").arg(subQuery).arg(i);
}
Вот тут точно не помню, как происходит объединение значений с Null, но, всё же:
Код:
query += GROUP BY timeTbl.Time

Выполняем запрос query.
Вроде бы примерно так. Настоятельно рекомендую перепроверить всё.


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 13:07
Советую почитать про Join и про вложенные запросы - это путь к решению вашей задачи


Название: Re: Структура бд
Отправлено: Bepec от Август 04, 2014, 13:10
Помучал я sqlbrowser - выбрать из одной таблицы данные из нескольких столбцов со сравнением одного нельзя. (да, я понял что написал :D)

По-моему тут просто неверный подход к желаемому результату. Точнее SQL не позволяет таких вещей.

Ваша "желаемая" выборка должна содержать N столбцов.
Их количество на момент запроса неизвестно.
Добавлять столбцы можно только видоизменяя запрос.
Вывод - ваше желание идёт вразрез с имеющимися возможностями и без логического блока, который определит количество и прочие связи столбцов (название/значение), тут не обойтись.

SQL просто не имеет возможностей выдавать фиг знает какие выборки. Оно рассчитано на работу с четкой структурой БД :)

PS это моё мнение, вполне возможно что я попробую join и его изменю :D


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 13:14
PS это моё мнение, вполне возможно что я попробую join и его изменю :D
О да  ;D ;D ;D ;D ;D


Название: Re: Структура бд
Отправлено: Bepec от Август 04, 2014, 13:17
Нет, не изменю. Проблема как и ожидалось находится в дублировании записей.

time/termo/baro/hermo
time/termo/hermo/baro
time/baro/termo/hermo
time/baro/hermo/termo
time/hermo/baro/termo/
time/hermo/termo/baro/

Конечно этого можно избежать сделав N вложенных селектов по числу уникальных устройств, но... Но я не настолько сильно хочу извращений :D

PS ну и кто не понял - то у нас будет N*N вариаций записей. Прикольно :)


Название: Re: Структура бд
Отправлено: ammaximus от Август 04, 2014, 13:25
В жизни не подумал бы, что так огребу на такой простой задаче...


Название: Re: Структура бд
Отправлено: Bepec от Август 04, 2014, 13:29
Задача поставлена неправильно. Вы как будто лопатой шуруп заворачиваете :)
Вон  __Heaven__ предложил рабочий способ с перебором всех уникальных устройства. И из этих данных вы можете сделать всё что угодно.

PS то что его способ вам не нравится или противен - это не повод его не применять :D


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 13:35
Сейчас в аксесе навояю для наглядности. (если получится вспомнить  :P )


Название: Re: Структура бд
Отправлено: Bepec от Август 04, 2014, 13:40
В Путь. Я Аксес вспоминаю с ужасом. Пришлось однажды делать там красивые выборочки. Где то строк на 50 запрос был :D


Название: Re: Структура бд
Отправлено: ammaximus от Август 04, 2014, 13:40
Цитировать
PS то что его способ вам не нравится или противен - это не повод его не применять
Ни в коем случае, мне нравится любой рабочий способ. Но книгу по sql я пока успел дочитать только до запросов к связанным таблицам, поэтому пытался решить задачу известными инструментами.


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 13:40
УСПЕХ!

Код:
SELECT DISTINCT mainTable.Time, barometer.Value as BAROMETER, thermometer.Value as THERMOMETER
FROM (mainTable

LEFT JOIN (SELECT mainTable.Time, mainTable.Value
                  FROM mainTable
                  WHERE mainTable.Device="barometer") AS barometer ON barometer.Time = mainTable.Time)

LEFT JOIN (SELECT mainTable.Time, mainTable.Value
                  FROM mainTable
                  WHERE mainTable.Device="thermometer") AS thermometer ON thermometer.Time = mainTable.Time



Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 13:43
Запрос составляете примерно тем методом, что я писал выше.
Работы от силы на 2 часа с изучением всех join и т.п.
Советую потренироваться в консоли или в том же Access


Название: Re: Структура бд
Отправлено: ammaximus от Август 04, 2014, 13:45
__Heaven__ , нет слов как я благодарен. Пантер, Верес всем спасибо за участие, пойду пробовать.


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 04, 2014, 13:55
Учтите, что если у вас какое-нибудь устройство выдаст 2 сообщения за минуту, то появятся дубликаты строк по времени двойного сигнала при данном запросе.


Название: Re: Структура бд
Отправлено: panAlexey от Август 09, 2014, 21:11
DISTINCT  есть в скулайте то?
пс. вроде есть: http://www.sqlite.org/lang_select.html


Название: Re: Структура бд
Отправлено: __Heaven__ от Август 09, 2014, 21:15
Group by наверняка везде есть


Название: Re: Структура бд
Отправлено: Bepec от Август 09, 2014, 23:06
Сейчас уже везде) Раньше в огнептице не был )