MySQL - динамический многоуровневый запрос кросс-вкладки [дубликат]

Каковы различия между операторами присваивания = и <- в R?

Как показывает ваш пример, = и <- имеют несколько иные приоритет оператора (который определяет порядок оценки, когда они смешиваются в одном выражении). Фактически, ?Syntax в R дает следующую таблицу приоритета оператора: от наивысшего до самого низкого:

…
‘-> ->>’           rightwards assignment
‘<- <<-’           assignment (right to left)
‘=’                assignment (right to left)
…

Но это единственная разница ?

Поскольку вы спрашивали о операторах присваивания : да, это единственная разница. Однако вам будет отказано в вере. Даже документация R в ?assignOps утверждает, что существует больше различий:

Оператор <- можно использовать в любом месте, тогда как оператор = разрешено на верхнем уровне (например, в полном выражении, введенном в командной строке) или в качестве одного из подвыражений в скобках списка выражений.

Давайте не будем слишком тонко очертить это: R-документация (тонко) неверна [ 1 ]. Это легко показать: нам просто нужно найти встречный пример оператора =, который не является (a) на верхнем уровне, и (b) подвыражение в скобках списка выражений (т.е. {…; …} ). - Без дальнейших церемоний:

x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1

Очевидно, что мы выполнили назначение, используя =, вне контекстов (a) и (b). Итак, почему документация о ключевой языковой функции R была неправильной на протяжении десятилетий?

Это связано с тем, что в синтаксисе R символ = имеет два разных значения, которые обычно объединяются:

  1. Первое значение является оператором присваивания . Это все, о чем мы говорили до сих пор.
  2. Второе значение - это не оператор, а токен синтаксиса , который сигнализирует с именем аргумент, передающий в вызове функции. В отличие от оператора = он не выполняет никаких действий во время выполнения, он просто меняет способ анализа выражения.

Давайте посмотрим.

В любом фрагменте кода общая форма ...

‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)

... = - это токен, который определяет передачу именованных аргументов: это not оператор присваивания. Кроме того, = полностью запрещен в некоторых синтаксических контекстах:

if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …

Любой из них вызовет ошибку «неожиданный» = «в ».

В любом другом контексте = ссылается на вызов оператора присваивания. В частности, просто размещение круглых скобок вокруг подвыражения делает любой из вышеперечисленных (a) действительными и (b) присвоением . Например, следующее выполняет назначение:

median((x = 1 : 10))

Но также:

if (! (nf = length(from))) return()

Теперь вы можете возразить, что такой код является жестоким (и вы можете быть правы). Но я взял этот код из функции base::file.copy (заменив <- на =) - это распространенный шаблон в большей части основной базы кода R.

Исходное объяснение от John Chambers , на котором, вероятно, основана документация R, на самом деле объясняет это правильно:

[= присваивание] разрешено только в двух местах в грамматике: на верхнем уровне (как полная программа или пользовательское выражение); и когда они изолированы от окружающей логической структуры, скобками или дополнительной парой круглых скобок.


Исповедь: я солгал раньше. Там есть еще одно различие между операторами = и <-: они вызывают различные функции. По умолчанию эти функции выполняют одно и то же, но вы можете переопределить любой из них отдельно, чтобы изменить поведение. Напротив, <- и -> (назначение слева направо), хотя и синтаксически различны, всегда вызывают функцию же . Переопределение одного также переопределяет другое. Знание этого редко бывает практичным , но оно может быть использовано для некоторых забавных махинаций .

2
задан Bill Karwin 31 August 2014 в 19:22
поделиться

2 ответа

Это называется сводной таблицей. Нехорошо производить:

SELECT ID, 
 MAX(CASE Type WHEN 202 THEN Degignation END) AS `202`
 MAX(CASE Type WHEN 234 THEN Degignation END) AS `234`
 MAX(CASE Type WHEN 239 THEN Degignation END) AS `239`
 Email
FROM mytable
GROUP BY ID, Email

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

2
ответ дан Bill Karwin 26 August 2018 в 09:10
поделиться

Хотя ответ Билла Карвина - правильный запрос, должен знать определенный набор столбцов, но для динамического сводного запроса существует способ взлома с помощью group_concat

SET @sql = NULL;
SELECT GROUP_CONCAT(DISTINCT
  CONCAT('MAX(CASE WHEN `Type` = ''',
         `Type`, 
         ''' THEN Degignation END) `Type_',
         `Type`,
         '`'
         )

 )
  INTO @sql
  FROM t;

SET @sql = CONCAT('SELECT ID, ', @sql, ', Email 
                     FROM t 
                    GROUP BY ID,Email');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

См. демонстрацию


Однако, используя group_concat , она имеет ограничение по умолчанию 1024 символа для конкатенации, а оставшийся результат будет усекается, поэтому, если у вас есть много разных типов, это будет сложно. Хотя вы можете увеличить предел для ограничения длины group_concat , как указано в руководстве, но также имеет зависимость от max_allowed_packet

1
ответ дан M Khalid Junaid 26 August 2018 в 09:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: