barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

суббота, 3 марта 2012 г.

CTM-колонки в БД TECDOC

Колонки в таблицах БД TECDOC, оканчивающиеся на "_CTM" и видимые через ODBC с типом CHAR, на самом деле являются набором бит, поэтому при их переносе лучше сразу их приводить к соответствующему типу (в зависимости от целевой СУБД), иначе они чрезмерно раздувают базу (вся база в формате INNODB разрастается до 100+ Гб). Назначение этих полей следующее: они определяют актуальность той или иной записи для различных стран, т.е. если некоторая запись актуальна для страны N, то на позиции N в этом наборе бит будет стоять "1". Исключение составляют только записи со всеми нулями в CTM - они, как я понял, актуальны для всех стран. 
Для России N = 186, однако с учетом того, что в начале строки стоит "0b", условие выбора записей, актуальных для нашей страны, будет выглядеть так (синтаксис MySQL):
... WHERE
LOCATE('1',`..._CTM`)=0
OR
SUBSTRING(`..._CTM` FROM 188 FOR 1)='1'

11 комментариев:

  1. А можна увидеть полностью запрос. А то с php пытаюсь выбрать только для одной страны, но никак не получается.

    ОтветитьУдалить
    Ответы
    1. SELECT * FROM `tof_country_designations` WHERE
      LOCATE('1',`CDS_CTM`)=0
      OR
      SUBSTRING(`CDS_CTM` FROM 188 FOR 1)='1'

      Удалить
    2. Это если я не ошибаюсь запрос к уже скопированой базе в mysql. А если при копировании выбирать только для определенного региона и не копировать _CTM поля.
      У меня получилось подключится к ODBC базе, но запрос SELECT * FROM TECDOC.TOF_MANUFACTURERS WHERE MFA_PC_CTM SUBRANGE(186 CAST INTEGER)=1 не дает в результате нужную информацию. В основном выдает сталую численность марок автомобилей вне зависимости от того какой бит проверять 186 или 150 или любой другой.

      ;

      Удалить
    3. Я к сожалению не знаток SQL-диалекта Transbase, и поэкспериментировать сейчас негде, поэтому ничего не могу сказать

      Удалить
  2. http://forum.forsag.org/viewtopic.php?f=7&t=9 здесь нашел ответ на свой вопрос - возможно пригодится и Вам.

    ОтветитьУдалить
    Ответы
    1. Возможно, спасибо.
      Похоже на оттрейсеный оригинальный запрос текдока, судя по конструкциям типа "1 = 1 AND 1 = 0 AND ...", помню такие.

      Удалить
    2. Это он и есть. Все запросы впринципе очень быстро трeйсером выдираються. А я поначалу их хотел сам вручную написать.

      Удалить
  3. так какой тип данных вы в результате использовали для CTM полей (в MySQL)?

    ОтветитьУдалить
    Ответы
    1. Я просто сделал булеву колонку "Россия / не Россия", и заполнил ее в соответствии с условием, которое описал в посте

      Удалить
  4. Т.е. получается этим кодом можно выбрать россию так?
    SELECT
    DISTINCT *
    FROM tof_manufacturers

    WHERE ( ( 1 = 1 AND 1 = 1
    AND (mfa_pc_mfc = 1 OR mfa_cv_mfc = 1)
    AND (mfa_pc_ctm subrange(186 CAST INTEGER) = 1 OR mfa_cv_ctm subrange(186 CAST INTEGER) = 1)
    )
    OR
    (1 = 1 AND 1 = 0 AND mfa_pc_mfc = 1 AND mfa_pc_ctm subrange(186 CAST INTEGER) = 1)
    OR (1 = 0 AND 1 = 1 AND mfa_cv_mfc = 1 AND mfa_cv_ctm subrange(186 CAST INTEGER) = 1)
    )

    ОтветитьУдалить
    Ответы
    1. Я то думаю, что WHERE (*****_CTM subrange(186 cast integer) = 1) выбирает слишком много (

      Удалить