Не прекращайте учебу с
LOKAD TV
where
и when
, которые можно использовать для отсеивания либо больших блоков сценария, либо отдельных операторов. В данном разделе вы найдете указания по практическому использованию этих средств./sample
в вашей учетной записи Lokad. Сценарий, приведенный ниже, достаточно сложен, и он содержит некоторые образцы фильтров, доступные в Envision. Если вы еще не прочитали статью «Ведение расчетов с помощью Envision», мы рекомендуем сделать это, прежде чем обратиться к данному разделу.
read "/sample/Lokad_Items.tsv" read "/sample/Lokad_Orders.tsv" as O show label "Filtering data" a1f1 tomato oend := max(O.Date) when date > oend - 365 LastYearQty = sum(O.Quantity) where StockOnHand + StockOnOrder > LastYearQty show table "Overstocked items, +1 year of stock" a2f3 tomato with Id Name StockOnHand + StockOnOrder as "Stock" LastYearQty where O.NetAmount > 1000 show table "Large transactions over $1000" a4f5 tomato with Id Name O.Date O.Quantity O.NetAmount O.Client lastDay := monday(oend) firstDay := lastDay - 52 * 7 when date >= firstDay & date < lastDay Week.sold := sum(O.NetAmount) show linechart "Sold by week" a6f7 tomato unit:"$" with Week.soldДля начала рекомендуем скопировать этот сценарий в вашу учетную запись Lokad и выполнить его, чтобы получить соответствующую панель управления. Если все сделано правильно, вы должны увидеть следующую панель управления.
when
, а второй второй блок — в 3-й строке с оператора where
.
when date > oend - 365 LastYearQty = sum(O.Quantity) where StockOnHand + StockOnOrder > LastYearQty show table "Overstocked items, +1 year of stock" a2f3 tomato with Id Name StockOnHand + StockOnOrder as "Stock" LastYearQtyВ языке Envision пробелы в начале строки играют большое значение. Несколько последовательных строк, начинающихся с одного и того же количества пробелов, называются блоком кода, и блоки могут вкладываться друг в друга (один блок может включать в себя другой блок).
when
отвечает за фильтрацию по времени, он применим ко всем таблицам со столбцом Date
. Оператор where
обычно используется для фильтрации наименований, и при его использовании фильтр применяется ко всем таблицам со столбцом Id
.where
, который начинается в третьей строке, вложен в блок when
, который начинается в первой строке.lastDay := monday(oend) firstDay := lastDay - 52 * 7 when date >= firstDay & date < lastDay Week.sold := sum(O.NetAmount) show linechart "Sold by week" a6f7 tomato unit:"$" with Week.soldВ данном сегменте оператор
and
говорит о том, что оба выражения, слева и справа от оператора, должны быть истинными. Логические операторы, поддерживаемые Envision, включают в себя следующее: and
, or
и not
. Кроме того, числа можно сравнивать с помощью числовых операторов: ==
(равенство), !=
(неравенство), <=
(меньше или равно), >=
(больше или равно), <
(меньше), >
(больше). В следующем сегменте кода показано, как эти операторы сочетаются и оцениваются.
a := 1 > 10 // false b := not a // true c := a | b // true d := a & b // false e := 10 >= 3 | 5 > 7 // true show table "Conditions" with a, b, c, d, eЕсли один блок фильтра вложен в другой блок фильтра, это равносильно использованию оператора
and
с двумя условиями, помещенными слева и справа от оператора and
.monday(oend)
. Это вызов функции с именем monday
. Данная функция возвращает дату последнего понедельника, который наступает не позже даты, указанной в качестве аргумента (включая ее). Таким образом, если в качестве аргумента указан понедельник, функция вернет ту же самую дату.monday()
используется для определения временного периода, состоящего из целых недель (вместо неполных недель). При выполнении еженедельного объединения данных должны использоваться только целые недели, в противном случае значения за первый и последний временной период могут быть необъективно низкими только по той причине, что учитываются неполные недели.oend := max(O.Date) when date > oend - 365 LastYearQty = sum(O.Quantity)Envision обрабатывает даты как количество дней в виде целых чисел, начиная с 1 января 2001 года. Это дает системе определенные преимущества, включая выполнение арифметических действий с датами. Например, вычитание 7 дней из определенной даты дает вам соответствующую дату на предыдущей неделе, а вычитание 365 дней — дату (приблизительную) в прошлом году.
date
работает особым образом. Переменная date
ссылается на все таблицы, в которых есть столбец Date
. В данном случае используется только одна таблица, O
, так что мы могли бы написать O.Date > oend - 365
. Однако синтаксис date
не только более краткий, он также применяется ко всем актуальным таблицам сразу. Если вместо объема продаж нам нужно было бы использовать объем закупок, мы могли бы прописать сценарий следующим образом:
// загрузка файла PurchaseOrders read "/sample/Lokad_PurchaseOrders.tsv" as PO // опущено when date > oend - 365 LastYearQty = sum(PO.Quantity)
where StockOnHand + StockOnOrder > LastYearQty show table "Overstocked items, +1 year of stock" a2f3 tomato with Id Name StockOnHand + StockOnOrder as "Stock" LastYearQtyУсловие вводится после ключевого слова
where
. Условие применяется к трем векторам, которые принадлежат таблице Items
. Это единственная таблица, имя которой не нужно указывать в виде префикса перед именем переменной. Например, при работе с таблицей заказов O
нужно прописывать выражение O.NetAmount
, а не только NetAmount
. Условие можно прочитать следующим образом: включать только наименования, для которых сумма наличных запасов и заказанных запасов больше, чем количество наименований, проданных за прошлый год.Items
задано, все таблицы, имеющие столбец Id
— то есть идентификаторы наименований в строках в соответствии с требованиями Envision — фильтруются таким же образом. Данная функция работает точно так же, как фильтрование по времени, описанное выше. При применении фильтра наименований не имеет смысла сохранять строки, содержащие данные о продажах или закупках, которые больше не привязаны к наименованиям, так как эти наименования были отфильтрованы.where StockOnHand > 5 GreaterThanFive = "yes" show table "Hello" with Name GreaterThanFive // ВЕРНО! // начиная с этой строки мы вышли из блока фильтра show table "Hello" with Name GreaterThanFive // НЕВЕРНО!В пятой строке присутствует ошибка, потому что вектор
GreaterThanFive
был определен только в строках, где условие StockOnHand > 10
истинно. Таким образом, этот вектор правильно задан в пределах блока, и потому он может быть использован, как показано в 5-й строке, однако данный вектор нельзя использовать вне блока фильтра, потому что некоторые его значения останутся неопределенными. Данную ситуацию можно исправить, надлежащим образом определив вектор для всех значений наименований, как показано ниже.
GreaterThanFive = "no" where StockOnHand > 5 GreaterThanFive = "yes" show table "Hello" with Name GreaterThanFive // ВЕРНО! // начиная с этой строки мы вышли из блока фильтра show table "Hello" with Name GreaterThanFive // ВЕРНО!Этот сегмент начинается с определения вектора
GreaterThanFive
для всех наименований (первая строка). Данное определение повторяется в четвертой строке для подгруппы наименований. Однако этот повтор не влияет на то, что вектор GreaterThanFive
открыто задан для всех наименований, и в результате задача отображения в двенадцатой строке теперь не имеет ошибок.where
. Рассмотрим строки, которые иллюстрируют эту возможность Envision.
where O.NetAmount > 1000 show table "Large transactions over $1000" a4f5 tomato with Id Name O.Date O.Quantity O.NetAmount O.ClientЗдесь мы фильтруем таблицу
O
, исключая все строки таблицы со значениями менее 1000 долларов. Строки, которые не отфильтровываются, отображаются с помощью оператора show table
во второй и третьей строках.
Данный пример показывает, как одна таблица может быть отфильтрована. Данный фильтр влияет только на таблицу O
, и данное условие не применяется к остальным таблицам.O
, рассчитывается в пределах блока фильтра, то доступ к этому вектору ограничен непосредственно самим блоком. Мы уже наблюдали подобное поведение при работе с наименованиями. Рассмотрим теперь, как система работает с произвольными таблицами в таких ситуациях.
where O.NetAmount > 1000 O.LargeTxn = "yes" show table "Large transactions" with Name O.LargeTxn // ВЕРНО! // последняя строка блока // отсуп отсутствует, так как блок закончился show table "Large transactions" with Name O.LargeTxn // НЕВЕРНО!Вектор
O.LargeTxn
не задан для всех строк таблицы O
, поэтому верной является только пятая строка, а десятая строка неверна. Также как и в предыдущем примере, сценарий можно исправить, определив надлежащим образом значение LargeTxn
для всей таблицы O
. Это можно сделать с помощью сценария, приведенного ниже.
O.LargeTxn = "no" where O.NetAmount > 1000 O.LargeTxn = "yes" show table "Large transactions" with Name O.LargeTxn // ВЕРНО! // последняя строка блока // отсуп отсутствует, так как блок закончился show table "Large transactions" with Name O.LargeTxn // ВЕРНО!Как правило, Envision стремится блокировать «утечки»: вектор, рассчитанный в пределах блока, можно использовать вне его при условии, что это не нарушает правило открытого определения всех значений вектора, если вектор указан справа от оператора присваивания.
// у каждого фильтра «where» // свой уровень отступа where O.Quantity > 10 where StockOnHand < 100 show table "Filtered orders" with O.Quantity // однако при использовании нескольких фильтров // требуется лишь один отступ where O.Quantity > 10 where StockOnHand < 100 // здесь отступа нет! show table "Filtered orders" with O.QuantityВторой блок имеет ту же семантику, что и первый, но для него требуется лишь один отступ. В общем виде синтаксис выглядит так:
where A when B where C show table "Filtered by A, B and C" with X // то же самое where A when B where C show table "Filtered by A, B and C" with X
and
&
. Тем не менее в Envision также есть ключевое слово and
, которое имеет немного другую семантику:
// два вложенных фильтра «where» where O.NetAmount > 1000 where StockOnHand > 10 show table "Filtered transactions" with Name O.Quantity // можно переписать как единый фильтр с помощью ключевого слова «and» where O.NetAmount > 1000 and StockOnHand > 10 show table "Filtered transactions" with Name O.QuantityИспользование ключевого слова
and
является строго эквивалентным использования фильтров where
. С помощью ключевого слова and
можно последовательно вводить различные фильтры, используя при этом лишь один отступ. В общем виде мы имеем следующее:
where A where B where C // опущено // можно переписать where A and B and C // опущеноНа практике ключевое слово
and
позволяет совмещать различные фильтры, которые не нужно использовать по-отдельности.keep
)keep
позволяет убрать отступы:
// с фильтра «where» начинается блок с отступом where O.Quantity > 10 // начало блока show table "Inside the filter" with sum(O.Quantity) // конец блока show table "Outside the filter" with sum(O.Quantity) // однако при использовании оператора «keep» // фильтр применяется без отступа keep where O.Quantity > 10 show table "Inside the filter" with sum(O.Quantity)Ключевое слово
keep
нужно ставить перед where
или when
, так как оно показывает, что фильтр применяется без отступов. Фильтр остается активным до конца заданного диапазона данных.
where A keep where B show table "Filtered by A and B" with X // конец фильтров А и В show table "Not filtered" with XТаким образом, если
keep
прописать в строке сценария без отступа, то фильтр применяется до самого конца сценария.when date > oend - 365 LastYearQty = sum(O.Quantity)Этот сценарий можно прописать следующим образом:
LastYearQty = sum(O.Quantity) when date > oend - 365Пользователям, знакомым с реляционными базами данных, такая конструкция может напомнить задание условий с оператором
where
в SQL. В Envision такой синтаксис позволяет избежать создания блоков, состоящих из 1 строки, когда в блоке нужно прописать всего одно выражение. Операторы where
и when
можно прописывать в виде «суффиксов» справа от операции присваивания.when
и where
. Envision также позволяет добавить к условию модификатор else
. Например, нельзя написать:
oend := max(O.Date) lastDay := monday(oend) Week.sold := sum(O.NetAmount) when date < lastDay show linechart "Sold by week" with Week.sold // НЕВЕРНОПотому что параметр
Week.sold
задан не для всего диапазона, что происходит из-за фильтра в предыдущей строке. Однако если добавить else
, мы сможем правильно задать Week.sold
:
oend := max(O.Date) lastDay := monday(oend) Week.sold := sum(O.NetAmount) when date < lastDay else 0 show linechart "Sold by week" with Week.sold // ВЕРНО