DBase, транспонирование всей таблицы

Работа VB и СУБД (Access, MSSQL, MySQL, Oracle и пр.)
Правила форума
При создании новой темы не забывайте указывать используемую СУБД.
Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

DBase, транспонирование всей таблицы

Сообщение Алексей К. » 26.05.2004 (Ср) 7:43

У меня вот такой вопрос:
Имеется база формата dbase вот такой структуры:
49 столбцов, 512 строк
Все записи integer: в первом столбце номер счетчика электроэнергии (1-512),
а в следующих 48 его показания за полчаса(шапка: 1 столбец 00.00-00.30, и т.д. до конца суток). Т.е. в базе показания всех счетчиков за сутки.
Мне нужно смотреть показания счетчиков как за сутки, так и с определенного часа по другой определенный час. В sql вроде есть сумма столбца. А суммы строки вроде нет (я точно не знаю). Можно как нибудь за раз транспонировать всю таблицу? Или так и придется писать запросы (условно): select 1 в столбце (00.00-00.30) потом select 2 в столбце (00.30-01.00) и так еще 48 раз а потом складывать - уж больно медленно будет работать. Мне нужно будет делать отчеты по показаниям счетчков за год за каждые сутки. У меня есть вариант на VB работающий - но он работает с текстовым файлом (dbf сохраняю в txt, sql почти не знаю).Вычисляю позицию записи в txt файле, сканирую че нужно в массив и там уже сумма элементов массива).Показания 10 счетчиков за год обратыбатывает минут 10 под win98 celeron 1,7. :( Хочется чтоб все летало.
Подскажите как мне быть.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 26.05.2004 (Ср) 8:28

А нельзя писать SELECT Col1+Col2+Col3+...+Col24 As ColAll ?
Lasciate ogni speranza, voi ch'entrate.

Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Сообщение Алексей К. » 26.05.2004 (Ср) 8:45

Наверно можно :D Яже говорю - sql почти или вовсе не знаю. Если не трудно, то приведите пожалуйста пример кода запроса суммы всей строки (столбец 2 по столбец 49). а так же максимальное, минимальное, среднее строки в этих столбцах.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 26.05.2004 (Ср) 9:15

Только столбцы я буду обозначать не "00.00-00.30", "00.30-01.00", а через C01...C48, C00 - номер счетчика
Код: Выделить всё
SELECT C00 As Counter
     , C01, C02, C03, ..., C48
     , (C01+C02+C03+...+C48) As ColAll
     , (C01+C02+C03+...+C48)/48 As ColAverage
FROM COUNTER_DATA
ORDER BY C00


Насчет минимального и максимального, то не получится, эти значения надо будет считать из выборки.
Lasciate ogni speranza, voi ch'entrate.

Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Сообщение Алексей К. » 26.05.2004 (Ср) 9:44

Спасибо побробую. Я еще только пробую работать с dbf в VB. Может кому не трудно приведет пример кода подключения базы "010104.dbf" (dbase 3) которая в папке "C:\База\". И как там sql инструкции оформляются. А то у меня MSDN нет :(

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 26.05.2004 (Ср) 10:10

Видимо используется DAO?
Код приблизително такой:
Код: Выделить всё
Dim dbf As DAO.Database, rs As DAO.Recordset
Const Base As String = "C:\BASE\", Table As String = "010104"
On Error Resume Next
Set dbf = DAO.OpenDatabase(Base, False, False, "dBASE IV;") 'LANGID=0x0419;CP=866;COUNTRY=0
If Err > 0 Then
  MsgBox "Не удается инициировать базу данных!" & vbNewLine & "Ошибка " & Err.Number & " - " & Err.Description, vbCritical
Else
  Set rs = dbf.OpenRecordset(Table, dbOpenTable)
  If Err > 0 Then
    MsgBox "Не удается открыть файл базы данных!" & vbNewLine & "Ошибка " & Err.Number & " - " & Err.Description, vbCritical
  Else
    MsgBox "Total records in '" & Table & "': " & rs.RecordCount
    'rs - Recordset
    rs.Close
    Set rs = New DAO.Recordset
    rs.Open "select * from " & Table & " order by 1"
    'Работа с рекордсетом
    rs.Close
  End If
  Set rs = Nothing
End If
dbf.Close
Set dbf = Nothing
On Error GoTo 0
Lasciate ogni speranza, voi ch'entrate.

Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Сообщение Алексей К. » 26.05.2004 (Ср) 10:34

Использую Microsoft DAO 3.6 object library
Set rs = New DAO.Recordset
На это ругается "Invalid use of New Keyword"

Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Сообщение Алексей К. » 26.05.2004 (Ср) 10:57

поправил на :
запрос = "select * from " & Table & " order by 1"
Set rs = dbf.OpenRecordset(запрос)
Заработало. Огромное спасибо!!!!!!
С DAO скорость выборки необходимых записей быстрей чем как поэлементное считывание из txt файла пока до нужной записи не дойдем? Или примерно одинаково? а то может не стоит браться

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 26.05.2004 (Ср) 11:11

Ну тогда убери эту строчку.
Кстати, а зачем тебе вообще SQL? Складывать вполне можно и непосредственно в базе. Вот пример (без обработки ошибок)
Код: Выделить всё
Dim dbf As DAO.Database, rs As DAO.Recordset
Dim vSum As Long, vAvg As Long, vMin As Long, vMax As Long
Dim I As Long, F() As String
Const Base As String = "C:\BASE\", Table As String = "010104"
ReDim F(0 To 47)
For I = 0 To 23
  F(2*I+0) = Format$(I,"00") & ".00" & Format$(I,"00") & ".30"
  F(2*I+1) = Format$(I,"30") & ".00" & Format$(I+1,"00") & ".00"
Next I
Set dbf = DAO.OpenDatabase(Base, False, False, "dBASE IV;")
Set rs = dbf.OpenRecordset(Table, dbOpenTable)
Do Until rs.EOF
  vSum = rs.Fields(F(0))
  vMin = 0
  vMax = 0
  For I = 1 To 47
    vSum = vSum + rs.Fields(F(I))
    If rs.Fields(F(I)) < rs.Fields(F(vMin)) Then vMin = I
    If rs.Fields(F(I)) > rs.Fields(F(vMax)) Then vMax = I
  Next I
  vAvg = vSum/48
  Debug.Print "Counter: " & rs.Fields(0)
  Debug.Print "  Sum = " & vSum
  Debug.Print "  Average = " & vAvg
  Debug.Print "  Min Value: " & rs.Fields(F(vMin)) & " on interval " & F(vMin)
  Debug.Print "  Max Value: " & rs.Fields(F(vMax)) & " on interval " & F(vMax)
  Debug.Print "--------"
  rs.MoveNext
Loop
Erase F()
rs.Close
Set rs = Nothing
dbf.Close
Set dbf = Nothing
Lasciate ogni speranza, voi ch'entrate.

Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Сообщение Алексей К. » 26.05.2004 (Ср) 12:42

Когда убираю On Error Resume Next, то выдает ошибку на строке:
Set rs = dbf.OpenRecordset(a$)
Ошибка:"3228 Выбранная последовательность сортировки не поддерживается операционной системой". Как избавиться от такой фигни? или просто игнорировать ошибку через On Error Resume Next?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 26.05.2004 (Ср) 13:21

А если использовать ConnectionString не "dBASE IV;" а "dBASE IV;LANGID=0x0419;CP=866;COUNTRY=0" ошибка не исчезает? А то я такой ошибки ни разу не встречал. Какая операционная система?
Или убери вообще предложение ORDER BY из текста запроса.
Lasciate ogni speranza, voi ch'entrate.

Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Сообщение Алексей К. » 26.05.2004 (Ср) 13:23

И еще проблемка:
По нажатию кнопки в label1 у меня записывается значение 3-й строки 2-го столбца. Значение записывается только со второго нажатия кнопки. Почему так?Я идиот! Убейте меня, кто-нибудь!?
Sub кнопка_click()
Dim dbf As DAO.Database, rs As DAO.Recordset
Base = "C:\"
Table = "g070603"
On Error Resume Next
Set dbf = DAO.OpenDatabase(Base, False, False, "dBASE IV;")
Set rs = dbf.OpenRecordset(Table, dbOpenTable)
rs.Close
a$ = "select * from " & Table & " order by 1"
Set rs = dbf.OpenRecordset(a$)
rs.GetRows (2)
Form1.Label1.Caption = rs.Fields(1)
rs.Close
Set rs = Nothing
dbf.Close
Set dbf = Nothing
End Sub

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 26.05.2004 (Ср) 13:27

А зачем ты открываешь таблицу, закрываешь ее и открываешь запрос? Я это только в качестве примера давал.
Я бы твой код написал так:
Код: Выделить всё
Sub кнопка_click()
Dim dbf As DAO.Database, rs As DAO.Recordset
Base = "C:\"
Table = "g070603"
On Error Resume Next
Set dbf = DAO.OpenDatabase(Base, False, False, "dBASE IV;")
a$ = "select * from " & Table & " order by 1"
Set rs = dbf.OpenRecordset(a$, dbOpenDynaset)
If rs.RecordCount > 2 Then
  rs.MoveFirst
  rs.MoveNext
  rs.MoveNext
  Form1.Label1.Caption = rs.Fields(1)
End If
rs.Close
Set rs = Nothing
dbf.Close
Set dbf = Nothing
End Sub
Lasciate ogni speranza, voi ch'entrate.

Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Сообщение Алексей К. » 26.05.2004 (Ср) 13:29

Поправил как ты сказал - все заработало как надо :D Спасибо тебе Alibek ОГРОМНОЕ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

    TopList