Как сравнить два столбца в excel на совпадения

Виртуальная перестановка данных.

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

Для этого нам понадобится функция ВЫБОР (CHOOSE в английском варианте). Она позволяет выбрать данные из какого-то массива по их индексу. Проще говоря, по порядковому номеру колонки.

Для поиска напитка используем формулу:

Вся хитрость состоит в указании массива данных для поиска. Мы выбираем два диапазона: С10:С25 – с кодами (первый), и В10:В25 – с напитками (второй). И из них при помощи ВЫБОР создаем новую виртуальную таблицу, с которой и будем работать.

Конструкция в виде массива {1;2} показывает, что мы берем сначала первый указанный диапазон C10:C25, потом – второй B10:B25, и формируем из них виртуальную таблицу с двумя колонками. В ней мы и производим поиск по первой и извлекаем значения – из второй

И при этом не важно, где они реально расположены на листе Excel. ВПР работает с виртуальным массивом, который мы сами создали

Как выделить совпадения и различия в 2 столбцах.

Когда вы сравниваете наборы данных в Excel, вы можете захотеть «визуализировать» элементы, которые присутствуют в одном, но отсутствуют в другом. Вы можете закрасить такие позиции любым цветом по вашему выбору с помощью формул. И вот несколько примеров с подробными инструкциями.

1. Выделите совпадения и различия построчно.

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

  • Выберите область, в которой вы хотите выделить.
  • Щелкните Условное форматирование> Новое правило…> Используйте формулу.
  • Создайте правило с простой формулой, например =$B2=$A2 (при условии, что строка 2 является первой строкой с данными, не включая заголовок таблицы). Пожалуйста, дважды проверьте, что вы используете относительную ссылку на строку (без знака $), как записано выше.

Чтобы выделить различия между колонками A и B, создайте правило с формулой =$B2<>$A2

Если вы новичок в условном форматировании Excel, смотрите пошаговые инструкции в статье Как закрасить строку или столбец по условию.

2. Выделите уникальные записи в каждом столбце.

Когда вы сравниваете два списка в Excel, вы можете выделить 3 типа элементов:

  • Предметы только в первом списке (уникальные)
  • Предметы только во втором списке (уникальные)
  • Элементы, которые есть в обоих списках (дубликаты).

О выделении дубликатов — смотрите пример выше. А сейчас рассмотрим, как выделить неповторяющиеся элементы в каждом из списков.

Предположим, что ваш список 1 находится в колонке A (A2:A8), а список 2 — в колонке C (C2:C8). Вы создаете правила условного форматирования с помощью следующих формул:

Выделите уникальные значения в списке 1 (столбик A): =СЧЁТЕСЛИ($A$2:$A$8;C$2)=0

Выделите уникальные значения в списке 2 (столбик C): =СЧЁТЕСЛИ($C$2:$C$8;$A2)=0

И получите следующий результат:

3. Выделите дубликаты в 2 столбцах.

Если вы внимательно следовали предыдущему примеру, у вас не возникнет трудностей с настройкой СЧЁТЕСЛИ, чтобы она находила совпадения, а не различия. Все, что вам нужно сделать, это установить счетчик больше нуля:

Вновь используем условное форматирование при помощи формулы.

Выделите совпадения в списке 1 (столбик A): =СЧЁТЕСЛИ($A$2:$A$8;C$2)>0

Выделите совпадения в списке 2 (столбик C): =СЧЁТЕСЛИ($C$2:$C$8;$A2)>0

Извлечь уникальные значения из диапазона.

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

Используем формулу массива

Здесь A2:C9 обозначает диапазон, из которого вы хотите извлечь уникальные значения. E1 – это первая ячейка столбца, в который вы хотите поместить результат. $2:$9 указывает на строки, содержащие данные, которые вы хотите использовать. $A:$C указывает на столбцы, из которых вы берёте исходные данные. Пожалуйста, измените их на свои собственные.

Нажмите , а затем перетащите маркер заполнения, чтобы вывести уникальные значения, пока не появятся пустые ячейки.

Как видите, извлекаются все уникальные и первые вхождения дубликатов.

Простые табличные подзапросы

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

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

Операция

Операция осуществляет проверку на принадлежность значения множеству, которое получается после выполнения подзапроса.

Пример 6.Определить наименования поставщиков, которые поставляют детали.

Такой подзапрос относится к табличным, так как возвращает множество значений.

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

СУБД сначала выполняет подзапрос, в результате чего получает множество номеров поставщиков, которые поставляют детали. Затем СУБД проверяет номер каждого поставщика из таблицы P на принадлежность полученному множеству. При вхождении в множество наименование поставщика помещается в результирующую таблицу.

Пример 7.Определить наименования поставщиков, которые не поставляют деталь с номером 2.

Пример 8.Определить наименования поставщиков, которые поставляют только деталь с номером 1.

Операции , ,

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

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

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

Ключевое слово является синонимом и используется для повышения наглядности текстов запросов.

Пример 9.Определить наименования поставщиков, которые поставляют детали.

Такой подзапрос относится к табличным, так как возвращает множество значений.

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

СУБД сначала выполняет подзапрос, в результате чего получает множество номеров поставщиков, которые поставляют детали. Затем СУБД проверяет номер каждого поставщика из таблицы P на равенство хотя бы одному из номеров из полученного множества. При выполнении условия наименование поставщика помещается в результирующую таблицу.

Пример 10.Определить наименование детали с максимальной ценой.

Последний пример можно решить следующим способом:

Здесь про это:

Рассмотрим несколько примеров, чтобы понять, чем отличается .iloc от .loc.

Выберем две строки и два столбца:

import pandas as pd
import numpy as np
df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')
print(df.iloc,  ])

Результат:

         Дата Менеджер
2  01.01.2016  Сидоров
3  01.01.2016  Сидоров

Осуществим выборку строк и столбцов с помощью среза:

import pandas as pd
import numpy as np
df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')
print(df.iloc)

Результат:

         Дата      Подразделение     Контрагент
2  01.01.2016  Отдел продвижения     Абакус ООО
3  01.01.2016  Отдел продвижения     Абакус ООО
4  01.01.2016       Отдел продаж  Билли Боб ООО
5  01.01.2016       Отдел продаж  Билли Боб ООО
6  01.01.2016       Отдел продаж  Билли Боб ООО
7  01.01.2016       Отдел продаж  Билли Боб ООО
8  01.01.2016  Отдел продвижения  Билли Боб ООО

Выберем 1 значение из столбца и указанной колонки:

import pandas as pd
import numpy as np
df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')
print(df.loc)

Результат:

Палатки

Вставка столбца

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

Вставка через панель координат

Одним из самых простых способов вставки является операция через горизонтальную панель координат Excel.

  1. Кликаем в горизонтальной панели координат с наименованиями колонок по тому сектору, слева от которого нужно вставить столбец. При этом колонка полностью выделяется. Кликаем правой кнопкой мыши. В появившемся меню выбираем пункт «Вставить».

После этого слева от выделенной области тут же добавляется новый столбец.

Добавление через контекстное меню ячейки

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

  1. Кликаем по любой ячейке, находящейся в столбце справа от планируемой к добавлению колонки. Кликаем по этому элементу правой кнопкой мыши. В появившемся контекстном меню выбираем пункт «Вставить…».

На этот раз добавление не происходит автоматически. Открывается небольшое окошко, в котором нужно указать, что именно пользователь собирается вставить:

  • Столбец;
  • Строку;
  • Ячейку со сдвигом вниз;
  • Ячейку со сдвигом вправо.

Переставляем переключатель в позицию «Столбец» и жмем на кнопку «OK».

После этих действий колонка будет добавлена.

Кнопка на ленте

Вставку столбцов можно производить, используя специальную кнопку на ленте.

  1. Выделяем ячейку, слева от которой планируется добавить столбец. Находясь во вкладке «Главная», кликаем по пиктограмме в виде перевернутого треугольника, расположенного около кнопки «Вставить» в блоке инструментов «Ячейки» на ленте. В открывшемся меню выбираем пункт «Вставить столбцы на лист».

После этого колонка будет добавлена слева от выделенного элемента.

Как выбрать строки из Pandas DataFrame по условию

Собираем тестовый набор данных для иллюстрации работы выборки по условию

Color Shape Price
Green Rectangle 10
Green Rectangle 15
Green Square 5
Blue Rectangle 5
Blue Square 10
Red Square 15
Red Square 15
Red Rectangle 5

Пишем скрипт:

import pandas as pd
Boxes = {'Color': ,
         'Shape': ,
         'Price': 
        }
df = pd.DataFrame(Boxes, columns= )
print (df)

Результат выполнения:

   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15
2  Green     Square      5
3   Blue  Rectangle      5
4   Blue     Square     10
5    Red     Square     15
6    Red     Square     15
7    Red  Rectangle      5

Синтаксис выборки строк из Pandas DataFrame по условию

Вы можете использовать следующую логику для выбора строк в Pandas DataFrame по условию:

df.loc

Например, если вы хотите получить строки с зеленым цветом , вам нужно применить:

df.loc

Где:

  • Color — это название столбца
  • Green — это условие (значение колонки)

А вот полный код Python для нашего примера:

import pandas as pd
Boxes = {'Color': ,
         'Shape': ,
         'Price': 
        }
df = pd.DataFrame(Boxes, columns= )
print (df.loc)

Результат:

   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15
2  Green     Square      5

Выберем строки, где цена равна или больше 10

Чтобы получить все строки, где цена равна или больше 10, Вам нужно применить следующее условие:

df.loc

Полный код Python:

import pandas as pd
Boxes = {'Color': ,
         'Shape': ,
         'Price': 
        }
df = pd.DataFrame(Boxes, columns= )
print (df.loc)

Результат:

   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15
4   Blue     Square     10
5    Red     Square     15
6    Red     Square     15

Выберем строки, в которых цвет зеленый, а форма — прямоугольник

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

  • Color зеленый; а также
  • Shape = прямоугольник

Мы будем использовать символ & для применения нескольких условий. В нашем примере код будет выглядеть так:

df.loc

Полный код примера Python для выборки Pandas DataFrame:

import pandas as pd
Boxes = {'Color': ,
         'Shape': ,
         'Price': 
        }
df = pd.DataFrame(Boxes, columns= )
print (df.loc)

Результат:

   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15

Выберем строки, где цвет зеленый ИЛИ форма прямоугольная

Для достижения этой цели будем использовать символ | следующим образом:

df.loc

Полный код Python 3:

import pandas as pd
Boxes = {'Color': ,
         'Shape': ,
         'Price': 
        }
df = pd.DataFrame(Boxes, columns= )
print (df.loc)

Результат:

   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15
2  Green     Square      5
3   Blue  Rectangle      5
7    Red  Rectangle      5

Выберем строки, где цена не равна 15

Мы будем использовать комбинацию символов !=, чтобы выбрать строки, цена которых не равна 15:

df.loc

Полный код Pandas DF на питоне:

import pandas as pd
Boxes = {'Color': ,
         'Shape': ,
         'Price': 
        }
df = pd.DataFrame(Boxes, columns= )
print (df.loc)

Результат работы скрипта Python:

   Color      Shape  Price
0  Green  Rectangle     10
2  Green     Square      5
3   Blue  Rectangle      5
4   Blue     Square     10
7    Red  Rectangle      5

Аргументы функции. Функция ВПР в Excel.

Искомое_значение.

Значение поиска, которое должно быть найдена в указанном нами диапазоне, в строке Таблица. В нашем примере мы указываем Конфеты Ж (ячейка Е3, Таблица №2). Так как это значение идет первое в столбце Название конфет, Таблица №2. (Это не принципиально, но удобно). Это значение, которое будет искать наша функция в Таблице №1.

Что бы выбрать нужную нам ячейку с значением, достаточно просто стать курсором в строку Искомое_значение, а потом клацнуть левой кнопкой мыши, по нужной ячейке в таблице ( В нашем примере ячейка Е3).

Таблица.

Здесь необходимо указать диапазон таблицы, в которой будет происходить поиск нужного нам значения и данных, которые мы хотим перенести. В нашем примере это Таблица №1. Значение, по которому будет происходить поиск это название конфет. Данные, которые мы хотим перенести, это цена конфет. Мы просто ставим курсор в строку Таблица и выделяем нужный нам диапазон. В нашем примере это диапазон Таблицы №1 — B1:C12. При этом ссылки нужно сделать абсолютными, добавив знак $. Это можно сделать, просто добавив эти знаки к ячейкам диапазона, в строке Таблица  —  $B$1:$C$12.

Можно присвоить нашему диапазону имя, и прописать его в строке Таблица.

Как это сделать. Выбираем нужный нам диапазон. Таблица №1. Выбираем закладку Формулы, кнопка Задать имя. Нажимаем. Появляется диалоговое окно Создание имени. Пишем любое имя. Но нужно его запомнить. Например Конфеты. Нажимаем ОК.

В строке Таблица, вместо диапазона нужно будет ввести имя, которое мы присвоили – Конфеты

Номер_столбца.

Функция ВПР осуществляет поиск значение в самом левом столбце таблицы указанного диапазона поиска. Функция присваивает этому столбцу номер 1, по умолчанию. В нашем примере самый левый столбце, это Название конфет в Таблице №1. А в строке Номер_столбца, нам нужно указать, какой номер по порядку имеет столбец, из которого нужно перенести данные. В нашем примере это столбце Цена в Таблице №1. Он «второй» по порядку, если считать слева на право, от столбца Название конфет, Таблица №1. Поэтому в строку Номер_столбца мы пишем цифру 2. Если бы столбец Цена, Таблица №1 был бы расположен по порядку не на втором месте, а предположим на десятом, то мы соответственно указывали бы в строке Номер_столбца цифру 10.

Интервальный _просмотр.

В этой строке мы пишем цифру ноль «0». Это значит, что функция ВПР будет осуществлять поиск точных совпадений между значениями поиска (Искомое_значение) и значениями в крайнем левом столбце диапазона поиска (Таблица). В нашем примере поиск точных совпадений будет происходить между столбцом Название конфет, Таблица №1, и столбцом Название конфет в Таблице №2.

Если мы поставим цифру один «1», функция будет осуществлять поиск не точного совпадения, а приближенного к нашему критерию поиска.

Вот как это выглядит все вместе.

Нажимаем ОК.

Протягиваем формулу по всему столбцу Цена в Таблице №2. Все цены перенесены с Таблице №1 в Таблицу №2.

Разбиение столбцов по позициям на строки

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

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

  • Позиции: 0, 6
  • Разбить на: строки

Примечание

Эта операция сначала начнет создание столбца из расположения 0 в положении 6. Есть еще один столбец, содержащий значения длиной 8 или более символов в текущем содержимом для просмотра данных.

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

Ограничения запроса ALTER

Запрос позволяет создавать и удалять отдельные элементы (столбцы) вложенных структур данных, но не вложенные структуры данных целиком. Для добавления вложенной структуры данных, вы можете добавить столбцы с именем вида и типом — вложенная структура данных полностью эквивалентна нескольким столбцам-массивам с именем, имеющим одинаковый префикс до точки.

Отсутствует возможность удалять столбцы, входящие в первичный ключ или ключ для сэмплирования (в общем, входящие в выражение ). Изменение типа у столбцов, входящих в первичный ключ возможно только в том случае, если это изменение не приводит к изменению данных (например, разрешено добавление значения в Enum или изменение типа с на ).

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

Запрос блокирует все чтения и записи для таблицы. То есть если на момент запроса выполнялся долгий , то запрос сначала дождётся его выполнения. И в это время все новые запросы к той же таблице будут ждать, пока завершится этот .

Для таблиц, которые не хранят данные самостоятельно (типа Merge и Distributed), всего лишь меняет структуру таблицы, но не меняет структуру подчинённых таблиц. Для примера, при ALTER-е таблицы типа , вам также потребуется выполнить запрос для таблиц на всех удалённых серверах.

Сложные табличные подзапросы

Операция EXISTS

Результат выполнения таких операций представляет собой значения или .

Для операции результат равен , если в возвращаемой подзапросом таблице присутствует хотя бы одна строка.

Если в результирующей таблице подзапроса пуста, то операция возвращает значение . Для операции используются обратные правила обработки.

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

Пример 11.Определить наименования поставщиков, которые поставляют детали.

Такой подзапрос относится к табличным, так как возвращает множество значений.

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

В этом случае выполнение оператора начинается с внешнего запроса, который поочередно отбирает каждую отдельную строку таблицы P. Для каждой выбранной строки СУБД выполняет подзапрос один раз. В результирующую таблицу помещаются только те наименования поставщиков, для которых подзапрос возвращает хотя бы одну строку.

Первой выбирается строка с информацией о поставщике Иванов. В подзапрос вместо P.pnum подставляется значение 1 (номер поставщика Иванова), после чего подзапрос выполняется.

Подзапрос возвращает три первых строки из таблицы PD, соответствующие поставкам Иванова, поэтому результат операции равен , и наименование Иванов помещается в результирующую таблицу.

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

Создание самосоединений

Самосоединение это обычное соединение языка SQL, которое соединяет таблицу саму с собой. Такое соединение позволяет сравнивать значения, хранящиеся в одном столбце таблицы.

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

Пример 12.Определить наименования поставщиков, которые поставляют и деталь с номером 1, и деталь с номером 2.

Один из вариантов решения задачи можно записать с помощью подзапроса следующим образом.

Тот же самый результат можно получить используя соединение таблицы PD с ее копией, назовем ее PD1, следующим образом:

Пример 13.Определить наименования поставщиков, которые поставляют и деталь с номером 1, и деталь с номером 2, и деталь с номером 3.

Предложение GROUP BY

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

Обычно предложение применяют, если формулировка задачи содержит фразу «для каждого…», «каждому..» и т.п.

Пример 18.Определить суммарный объем деталей, поставляемых каждым поставщиком.

pnum sum
1 600
2 400
3 1000

Выполнение запроса можно описать следующим образом: СУБД разбивает таблицу PD на три группы, в каждую из групп помещаются строки с одинаковым значением номера поставщика. Затем к каждой из полученных групп применяется агрегатная функция SUM, что дает единственное итоговое значение для каждой группы.

Рассмотрим два похожих примера.

В примере 1 определяется минимальный объем поставки каждого поставщика. В примере 2 определяется объем минимальной поставки среди всех поставщиков.

Пример 1:

Пример 2:

Результаты запросов представлены в следующей таблице:

pnum min max
1 100 100
2 150
3 1000

Следует обратить внимание, что в первом примере мы можем вывести номера поставщиков, соответствующие объемам поставок, а во втором примере – не можем. Все имена столбцов, перечисленные после ключевого слова SELECT должны присутствовать и в предложении GROUP BY, за исключением случая, когда имя столбца является аргументом агрегатной функции

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

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

Если предложение расположено после предложения , то группы создаются из строк, выбранных после применения .

Пример 19.Для каждой из деталей с номерами 1 и 2 определить количество поставщиков, которые их поставляют, а также суммарный объем поставок деталей.

Результат запроса:

dnum COUNT SUM
1 3 1250
2 2 450

Общие положения

Создать новую базу данных с названием DB_Books с помощью оператора Create Database, создать в ней перечисленные таблицы c помощью
операторов Create table по примеру лабораторной работы №1. Сохранить файл программы с названием ФамилияСтудента_ЛАб_1_DB_Books. В
утилите SQL Server Management Studio с помощью кнопки «Создать запрос» создать отдельные программы по каждому запросу, которые сохранять на диске с названием: ФамилияСтудента_ЛАб_2_№_задания. В сами программы копировать текст задания в виде комментария. Можно сохранять все выполненные запросы в одном файле. Для проверки работы операторов SELECT предварительно создайте программу, которая с помощью операторов INSERT заполнит все таблицы БД DB_Books несколькими записями, сохраните программы с названием ФамилияСтудента_ЛАб_2_Insert.

Оператор Select используется для выбора данных из таблиц.

Для выбора данных из некоторой таблицы нет необходимости знать имена всех ее полей. Звездочка (*) после оператора SELECT означает выбор всех столбцов таблицы. Другими словами, эта команда просто выводит все данные таблицы. Синтаксис:

SELECT * 
FROM <имя таблицы> 

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

Пример. Выбрать сведения о количестве страниц из таблицы Books (поле Pages).

SELECT Pages
FROM Books

Пример. Выбрать все данные из таблицы Books.

SELECT *
FROM Books
Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: