Я думаю, что включение ORDER BY
в sqldf
важно, поскольку оно указывает на тот факт, что в SQL упорядочение никогда не гарантируется, если явно не указано иное.
Если вы выполняли простое ORDER BY
просто "увеличивая" обе переменные, перевод на order
в R будет прямым. Однако, поскольку одна переменная уменьшается, а другая увеличивается, order
сама по себе не справляется с этим. Однако, как предполагает { ссылка }, мы можем сделать то же самое с xtfrm
.
out1 <- merge(x = Sales, y = Clients, by = NULL)
out1 <- out1[order(-xtfrm(out1$State), out1$CustomerID.y),]
out2 <- sqldf::sqldf(
"SELECT *
FROM Sales
CROSS JOIN Clients
ORDER BY State DESC, Clients.CustomerID")
### proof they are identical
all(unlist(Map(`==`, out1, out2)))
# [1] TRUE
Вспомогательная функция xtfrm
здесь позволяет нам отрицать «значения» столбец для целей сортировки. From ?xtfrm
:
Универсальная вспомогательная функция c, которая генерирует вектор цифр c, который будет сортироваться в том же порядке, что и 'x'.
Если бы поле уже числилось c, мы могли бы просто сделать order(-State, CustomerID.y)
, но тот факт, что оно character
, требует дальнейшего шага. Ar go xtfrm
.
Редактировать : в комментариях определено, что ОП хочет имитировать c порядок сортировки merge
в SQL заявление. К сожалению, поскольку это декартово произведение двух кадров, сортировка не применяется: merge
просто cbind
s все строки первого кадра относительно первого ряда второго кадра, а затем повторяется с каждым рядом второго кадра.
Это можно продемонстрировать, используя некоторый код из merge
:
nx <- nrow(x) # Sales
ny <- nrow(y) # Clients
expand.grid(seq_len(nx), seq_len(ny))
# Var1 Var2
# 1 1 1
# 2 2 1
# 3 3 1
# 4 4 1
# 5 5 1
# 6 1 2
# ...
# 33 3 7
# 34 4 7
# 35 5 7
, где каждое число является строкой из соответствующих кадров (x
для Var1
, y
для Var2
). Если исходные данные:
## Sales ## Clients
Product CustomerID Price CustomerID State
1 Toaster 1_2019 37 1 2_2019 AZ
2 Radio 1_2019 33 2 3_2019 MA
3 Radio 2_2019 33 3 4_2019 AZ
4 TV 3_2019 408 4 1_2020 IL
5 Toaster 1_2020 37 5 2_2020 MA
6 TV 2_2020 408
7 TV 3_2020 408
, то это приводит к
out1
# Product CustomerID.x Price CustomerID.y State
# 1 Toaster 1_2019 37 2_2019 AZ
# 2 Radio 1_2019 33 2_2019 AZ
# 3 Radio 2_2019 33 2_2019 AZ
# 4 TV 3_2019 408 2_2019 AZ
# 5 Toaster 1_2020 37 2_2019 AZ
# 6 TV 2_2020 408 2_2019 AZ
# 7 TV 3_2020 408 2_2019 AZ
# 8 Toaster 1_2019 37 3_2019 MA
# ...
# 33 Toaster 1_2020 37 2_2020 MA
# 34 TV 2_2020 408 2_2020 MA
# 35 TV 3_2020 408 2_2020 MA
, что очень сильно разрушит любую сортировку, присутствующую в x
(Sales
), даже если y
(Clients
) поставляется предварительно отсортированным (что он и делает).
Из-за этого , если вам нужно соответствие между решениями R и SQL перекрестного соединения, я предлагаю самый прозрачный / прозрачный способ - использовать merge
в R, а затем применять порядок после merge
таким же образом, как SQL. На самом деле, с точки зрения педагога, задайте вопрос: «Какой порядок имеет смысл для людей?» Если вы утверждаете во время плана урока, что порядок не может быть гарантирован до тех пор, пока он явно не будет решительно вовлечен в процесс (с помощью пункта dplyr::arrange
или ORDER BY
*1062*). Найдите интуитивно понятный порядок данных и затем продемонстрируйте, что как в R, так и в SQL.
Примечания:
- Ваш запрос
sqldf
приводит к столбцам с таким же именем, это приводит к некоторым ошибкам после sqldf
, если вы начинаете играть с колонками. Это можно исправить с помощью select ... as ...
именования полей. - Lexicographi c сортировка ваших данных, к сожалению, на данный момент нелогична: наличие года в конце идентификатора клиента предлагает (да, я предполагаю) график регистрации клиентов, но они будут отсортированы в первую очередь по количеству ведущих. Подобно тому, как
"2020-05-04"
сортирует правильно даже в виде строки, в то время как "05/04/2020"
- нет, он может поддерживать более интуитивную сортировку, чтобы наиболее значимая часть была ведущей частью строк идентификатора. Или сделайте их целыми числами. Или UUID (v4, конечно), это всегда весело.