в Qlikview возможно ли выполнить объединение «строгих полей»?

#performance #concatenation #qlikview

#Производительность #объединение #qlikview

Вопрос:

я использую qlikview уже несколько лет, и простая проблема, с которой я сталкиваюсь почти ежедневно, заключается в необходимости объединения таблиц с разными полями, когда мне нужны только некоторые из них.

Например, допустим, у меня есть следующие таблицы на отдельных QVDS

таблица1:

введите описание изображения здесь

таблица2:

введите описание изображения здесь

мне нужно создать итоговую таблицу ТОЛЬКО с field_1, field_2 и field_3, но если я сделаю

введите описание изображения здесь

я получаю сообщение об ошибке, что field_2 не существует в table2. я могу указать null() как field_2, когда я имею дело с небольшим количеством таблиц, где я знаю, что поле не существует, но когда я перебираю более 500 QVDS, где у некоторых есть поле, а у некоторых нет, мне нужен способ определить это.

прямо сейчас у меня есть два способа решения этой проблемы:

  1. сначала я загружаю qvd с помощью * и использую FIELDNUMBER, чтобы проверить, существует ли поле, и помещаю поле в переменную для использования во время загрузки.

пример:

введите описание изображения здесь

  1. я создаю пустую стартовую таблицу с полями, для которых установлено значение null, и объединяю ее с помощью load *, чтобы сгенерировать отсутствующие поля (используя преимущество «генерировать отсутствующие поля с null»)

пример:

Скриншот из 2020-09-02 20-48-43.png

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

есть ли способ выполнить объединение, которое принимает только столбцы, уже присутствующие в первой таблице, завершает отсутствующие столбцы нулем, но автоматически исключает все остальные необязательные поля?

я пытался использовать предыдущую загрузку перед загрузкой с помощью *, но это не удается, когда одного из полей нет в qvd. есть идеи?

PS: я знаю, что описанные мной способы решают проблему, но я ищу лучшее решение с точки зрения производительности и скорости.

Ответ №1:

При объединении двух таблиц в Qlik нет необходимости в совпадении полей. Вы даже можете объединить две таблицы с совершенно разными полями, и Qlik не будет жаловаться. Qlik просто добавит null для полей, которые отсутствуют.

Смотрим на приведенный ниже скрипт — у нас есть две таблицы Table1 и Table2 .

  • Table1 поля: field1 , field2 , field3
  • Table2 поля: field3 , field4 , field5

При загрузке всех полей из Table1 и объединении только field3 из Table2 результат будет:

введите описание изображения здесь

field1 и field2 заполняются null для строк, которые получены из Table2

 Table1:
Load * Inline [
  field1, field2, field3
  1     , 2     , 3     
  4     , 5     , 6
];

Table2:
Load * Inline [
  field3, field4, field5
  1     , 2     , 3
  4     , 5     , 6
];

NoConcatenate


ConcatenatedTable:
Load
  field1,
  field2,
  field3
Resident
  Table1
;

Concatenate

Load
  field3
Resident
  Table2
;

Drop Tables Table1, Table2;
  

Комментарии:

1. спасибо ответчику, возможно, я неправильно выразился: я знаю, что принудительное объединение генерирует недостающие поля в null (я использую его во втором примере). моя проблема в том, что когда у меня есть 500 qvd с f1, f2, f3, f4 и т.д., И я хочу объединить ТОЛЬКО [f1 f2 f3], но в некоторых таблицах нет f2, и я не могу заранее знать, какие из них есть, я в конечном итоге либо предварительно загружаю каждый qvd, чтобы проверить, существует ли поле, либо принудительно объединяю весь файл в пустую таблицу. оба решения мне не нравятся, потому что я в конечном итоге загружаю в память намного больше данных, чем мне действительно нужно, и теряю производительность.

Ответ №2:

Это другой подход, у меня недостаточно большого набора данных, чтобы проверить его производительность, но, по крайней мере, решает проблему наличия явных имен полей в скрипте, что может быть кошмаром для поддержания.

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

 for each file in FileList('<folder><files>*')

   RawTable:
   CrossTable(Field, Data, 2)
   LOAD FileName() as FileName,
         RowNo() as RowId,
         *
   FROM
    [$(file)]
    (txt, utf8, no labels, embedded labels, delimiter is ',');

next file;
  

Это создаст таблицу, содержащую 4 поля: исходное имя файла (FileName), номер строки внутри этого файла (RowId), имя столбца (Field) и его значение (Data).

Затем создайте свою конечную таблицу, чтобы она содержала ссылки на каждый файл и каждую известную строку :

 DataTable:
LOAD
    DISTINCT FileName,
    RowId
Resident RawTable;
  

Затем создайте таблицу поддержки с отличным именем каждого известного поля в ваших файлах :

 FieldTable:
LOAD
    Distinct Field as KnownField 
Resident RawTable;
  

Наконец, начинается волшебство, когда вы поле за полем слева присоединяете их к DataTable :

 LET NumFields = NoOfRows('FieldTable');

FOR i = 0 to $(NumFields) - 1
    LET vField = Peek('KnownField', $(i), 'FieldTable');

    TRACE $(vField);

    Left Join(DataTable)
    LOAD
        FileName,
        RowId,
        Data as $(vField)
    Resident RawTable
    WHERE Field = '$(vField)';  
NEXT;
  

Наконец, просто некоторая очистка :

 DROP TABLE RawTable;
DROP TABLE FieldTable;
  

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

Комментарии:

1. спасибо за ответ, я использую аналогичную логику, когда не знаю имен полей загружаемых наборов данных и хочу сопоставить их со списком возможных имен полей; но поскольку FOR-lines в qlikview невероятно малопроизводительны, я предпочитаю избегать их, когда могу. приведенные мной примеры уже работают, я просто пытаюсь понять, есть ли более эффективный способ сделать это

Ответ №3:

Для более эффективного решения вы можете сначала извлечь метаданные каждого qvd, чтобы получить содержащие их поля, а затем настроить логику итерации qvd на основе этого.

Вот основной скрипт, который выдает вам имена полей файла qvd:

 LOAD
    "FieldName"
FROM [some.qvd]
(XmlSimple, table is [QvdTableHeader/Fields/QvdFieldHeader]);
  

Комментарии:

1. я думал об этом, но это то же самое, что загрузить файл и использовать fieldnumber для проверки, что означает, что я в конечном итоге дважды читаю один и тот же файл с диска. я знаю, что пытаюсь повысить производительность на 0,5%, используя странный / оккультный код, но я должен был спросить