Сделайте SELECT
с предложением GROUP BY
. Скажем, name - это столбец, в котором вы хотите найти дубликаты:
SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;
Это вернет результат с именем name в первом столбце , и количество раз, сколько раз это значение появляется во втором.
Выражение: Что-то, что оценивает к значению. Пример: оператор 1+2/x
: строка А кода, который делает что-то. Пример: GOTO 100
На самых ранних языках программирования общего назначения, как ФОРТРАН, различие было совершенно ясно. В ФОРТРАНЕ оператор был одной единицей выполнения, вещь, которую Вы сделали. Единственная причина это не назвали "строкой", состояла в том, потому что иногда это охватывало несколько строк. Выражение самостоятельно ничего не могло сделать..., что необходимо было присвоить его переменной.
1 + 2 / X
ошибка в ФОРТРАНЕ, потому что он ничего не делает. Необходимо было сделать что-то с тем выражением:
X = 1 + 2 / X
ФОРТРАН не имел грамматики, поскольку мы знаем это today— та идея была изобретена, наряду с Формой Бэкуса-Наура (BNF), как часть определения Алгола 60. В той точке семантический различие ("имеют значение" по сравнению с, "делает что-то"), хранился в [1 115] синтаксис : один вид фразы был выражением, и другой был оператором, и синтаксический анализатор мог сказать им независимо.
Разработчики более поздних языков размыли различие: они позволили синтаксическим выражениям делать вещи, и они позволили синтаксические операторы, которые имели значения. Самым ранним популярным примером языка, который все еще выживает, является C. Разработчики C поняли, что никакой вред не был причинен, если Вам разрешили оценить выражение и выбросить результат. В C каждое синтаксическое выражение может быть превращенным в оператор только путем прикрепления точки с запятой вдоль конца:
1 + 2 / x;
полностью законный оператор даже при том, что абсолютно ничего не произойдет. Точно так же в C, выражение может иметь побочные эффекты — это может изменить что-то.
1 + 2 / callfunc(12);
, потому что callfunc
мог бы просто сделать что-то полезное.
, Как только Вы позволяете любому выражению быть оператором, Вы могли бы также позволить оператор присваивания (=) в выражениях. Вот почему C позволяет Вам сделать вещи как [1 126]
callfunc(x = 2);
, Это оценивает выражение x = 2 (присвоение значения 2 к x) и затем передает это (2) к функции callfunc
.
Это размывание выражений и операторов происходит во всех C-производных (C, C++, C# и Java), которые все еще имеют некоторые операторы (как while
), но которые позволяют почти любому выражению использоваться в качестве оператора (в C# только присвоение, назовите, увеличьте, и декрементные выражения могут использоваться в качестве операторов; см. ответ Scott Wisniewski ).
Наличие двух "синтаксических категорий" (который является техническим именем для вида вещи, которая операторы и выражения) может привести к дублированию усилия. Например, C имеет две формы условного выражения, форма оператора
if (E) S1; else S2;
и форма выражения
E ? E1 : E2
, И иногда люди хотят дублирование, которое не является там: в стандарте C, например, только оператор может объявить новый локальный variable— но эта способность достаточно полезна, что компилятор C GNU обеспечивает расширение GNU, которое позволяет выражению объявить локальную переменную также.
Разработчикам других языков не нравился этот вид дублирования, и они видели рано на что, если выражения могут иметь побочные эффекты, а также значения, то синтаксический различие между операторами и выражениями не все это useful— таким образом, они избавились от него. Haskell, Значок, Lisp и ML являются всеми языками, которые не имеют синтаксического statements— у них только есть выражения. Даже класс структурировал цикличное выполнение, и условные формы считают выражениями, и у них есть values— но не очень интересные.
Выражения могут быть оценены для получения значения, тогда как операторы не возвращают значение (они имеют тип пусто ).
выражения Вызова функции можно также считать операторами, конечно, но если среда выполнения не имеет специальную встроенную переменную для содержания возвращенного значения, нет никакого способа получить его.
Ориентированный на оператор на языки требуют, чтобы все процедуры были списком операторов. Ориентированные на выражение языки, который является, вероятно, всеми функциональными языками, являются списками выражений, или в tha случае LISP, одно долгое S-выражение, которое представляет список выражений.
, Хотя оба типа могут быть составлены, большинство выражений может быть составлено произвольно, пока типы совпадают. Каждый тип оператора поступает по-своему создания других операторов, если они могут сделать это все. Foreach и если операторы требуют или единственного statment или что все зависимые операторы входят в блок операторов, один за другим, если подоператоры не допускают свои собственные подоператоры.
Операторы могут также включать выражения, где выражение действительно не включает операторов. Одним исключением, тем не менее, было бы лямбда-выражение, которое представляет функцию, и так может включать что-либо, что функция может iclude, если язык только не допускает ограниченные лямбды, как лямбды отдельного выражения Python.
На основанном на выражении языке, все, в чем Вы нуждаетесь, является отдельным выражением для функции, так как все управляющие структуры возвращают значение (многие из них возвращают NIL). Нет никакой потребности в операторе возврата, так как оцененное в последний раз выражение в функции является возвращаемым значением.
Просто: выражение оценивает к значению, оператор не делает.
Можно найти это на Википедия , но выражения оценены к некоторому значению, в то время как операторы не имеют никакого оцененного значения.
Таким образом, выражения могут использоваться в операторах, но не наоборот.
Примечание, что некоторые языки (такие как Lisp, и я верю Ruby и многим другим) не дифференцируют оператор по сравнению с выражением... на таких языках, все - выражение и может быть объединено в цепочку с другими выражениями.
Выражение - что-то, что возвращает значение, тогда как оператор не делает.
Для примеров:
1 + 2 * 4 * foo.bar() //Expression
foo.voidFunc(1); //Statement
Грандиозное предприятие между этими двумя состоит в том, что можно объединить выражения в цепочку вместе, тогда как операторы не могут быть объединены в цепочку.
Я хотел бы сделать маленькое исправление к ответу Joel выше.
C# не позволяет всем выражениям использоваться в качестве операторов. В частности, только присвоение, назовите, увеличьте, и декрементные выражения могут использоваться в качестве операторов.
, Например, компилятор C# отметит следующий код как синтаксическую ошибку:
1 + 2;
Примечание, которое в C, "=" является на самом деле оператором, который делает две вещи:
Вот является извлечение из ANSI C грамматикой. Вы видите, что C не имеет многих различных видов операторов..., большинство операторов в программе является операторами выражения, т.е. выражением с точкой с запятой в конце.
statement
: labeled_statement
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
;
expression_statement
: ';'
| expression ';'
;
Некоторые вещи об основанных на выражении языках:
<час>самый важный: Все возвращает значение
<час>нет никакого различия между фигурными скобками и не заключает в фигурные скобки для разграничивания блоков кода и выражений, так как все - выражение. Это не предотвращает лексический обзор хотя: локальная переменная могла быть определена для выражения, в котором содержится его определение, и все операторы содержатся в этом, например.
<час> На основанном на выражении языке, все возвращает значение. Это может быть немного странно сначала - Что делает (FOR i = 1 TO 10 DO (print i))
возврат?
Некоторые простые примеры:
(1)
возвраты 1
(1 + 1)
возвраты 2
(1 == 1)
возвраты TRUE
(1 == 2)
возвраты FALSE
(IF 1 == 1 THEN 10 ELSE 5)
возвраты 10
(IF 1 == 2 THEN 10 ELSE 5)
возвраты 5
Пара более сложных примеров:
OpenADoor(), FlushTheToilet()
или TwiddleYourThumbs()
возвратит своего рода приземленное значение, такой как хорошо, Сделанный, или Успех. (print i)
выражение быть оцененным 10 раз, каждый раз возвращаясь i как строка. Заключительное время посредством возвратов 10
, наш окончательный ответ Это часто требует, чтобы небольшое изменение мышления получило все возможное от основанного на выражении языка, так как то, что все - выражение, позволяет 'встроить' много вещей
Как быстрый пример:
FOR i = 1 to (IF MyString == "Hello, World!" THEN 10 ELSE 5) DO ( LotsOfCode )
совершенно допустимая замена для не основанный на выражении
IF MyString == "Hello, World!" THEN TempVar = 10 ELSE TempVar = 5 FOR i = 1 TO TempVar DO ( LotsOfCode )
В некоторых случаях, расположение, что основанные на выражении разрешения на код чувствуют себя намного более естественными для меня
, Конечно, это может привести к безумию. Как часть проекта хобби в основанном на выражении языке сценариев под названием MaxScript, мне удалось придумать эту строку монстра
IF FindSectionStart "rigidifiers" != 0 THEN FOR i = 1 TO (local rigidifier_array = (FOR i = (local NodeStart = FindsectionStart "rigidifiers" + 1) TO (FindSectionEnd(NodeStart) - 1) collect full_array[i])).count DO
(
LotsOfCode
)
Оператор является особым случаем выражения, один с void
тип. Тенденция языков рассматривать операторы по-другому часто вызывает проблемы, и было бы лучше, если бы они были правильно обобщены.
, Например, в C# у нас есть очень полезное Func<T1, T2, T3, TResult>
перегруженная группа универсальных делегатов. Но у нас также должно быть соответствие Action<T1, T2, T3>
набор также, и программирование высшего порядка общего назначения постоянно должно дублироваться для контакта с этим неудачным раздвоением.
Тривиальный пример - функция, которая проверяет, является ли ссылка нулевой прежде, чем звонить на другую функцию:
TResult IfNotNull<TValue, TResult>(TValue value, Func<TValue, TResult> func)
where TValue : class
{
return (value == null) ? default(TValue) : func(value);
}
компилятор мог иметь дело с возможностью TResult
являющийся void
? Да. Все, что это должно сделать, требуют, чтобы возврат сопровождался выражением, которое имеет тип void
. Результат default(void)
имел бы тип void
, и func, передаваемый в, должен будет иметь форму Func<TValue, void>
(который был бы эквивалентен [1 110]).
Много других ответов подразумевают, что Вы не можете объединить операторы в цепочку как Вы, может с выражениями, но я не уверен, куда эта идея прибывает из. Мы можем думать ;
, который появляется после операторов как двоичный инфиксный оператор, беря два выражения типа void
и комбинируя их в отдельное выражение типа void
.
Func<Task>
вместо этого, тогда можно сделать FooAsync().Then(BarAsync).Then(FubarAsync)
.
– Lee
31 January 2013 в 18:20
Фактическое основание этих понятий:
Выражения : синтаксическая категория, экземпляр которой может быть оценен к значению.
Оператор : синтаксическая категория, экземпляр которой может быть связан с оценками выражения и законченным значением оценки (если таковые имеются) не гарантируется доступная.
, Кроме того, к очень начальному контексту для ФОРТРАНА в ранние десятилетия, и определения выражений и операторы в принятом ответе являются, очевидно, неправильными:
sizeof
оператор, никогда не оценивается. (BTW, я хочу добавить [необходима цитата] к тому ответу относительно материалов о C, потому что я не могу вспомнить, имеет ли DMR такие мнения. Это кажется не, иначе не должно быть никаких причин сохранить дублирование функциональности в дизайне C: особенно, оператор запятой по сравнению с операторами.)
(Следующее объяснение не является прямым ответом на исходный вопрос, но я чувствую это необходимый, чтобы разъяснить, что что-то уже ответило здесь.)
, Тем не менее, сомнительно, что нам нужна определенная категория "операторов" на языках программирования общего назначения:
begin
в Схеме) или синтаксический сахар одноместных структур. ++i + ++i
бессмысленно в C.) Итак, почему операторы? Так или иначе история уже является путаницей. Кажется, что большинство разработчиков языка не берет свой выбор тщательно.
Хуже, это даже дает некоторым энтузиастам системы типов (кто не достаточно знаком с МН историей), некоторые неправильные представления, которые системы типов должны иметь важные вещи сделать с более существенными проектами правил об операционной семантике.
Серьезно, рассуждая в зависимости от типов не то, что плохо во многих случаях, но особенно не конструктивен в этом специальном. Даже эксперты могут завинтить вещи.
, Например, кто-то подчеркивает хорошо вводящую природу как центральный аргумент против традиционной обработки неразграниченных продолжений . Хотя заключение несколько разумно, и понимание о составленных функциях в порядке (, но все еще слишком наивный к сущности ), этот аргумент не является звуковым, потому что это полностью игнорирует "подход" канала стороны на практике как _Noreturn any_of_returnable_types
(в C11) для кодирования Falsum
. И строго говоря, абстрактная машина с непредсказуемым состоянием не идентична "разрушенному компьютеру".
Для объяснения важных различий в компоновке (цепочности) выражений и утверждений, моя любимая ссылка - это статья Джона Бэкуса о премии Тьюринга Can программирование должно быть освобождено от стиля фон Неймана? .
Императивные языки (Fortran, C, Java, ...) делают упор на операторы для структурирования программ и имеют выражения как своего рода размышления. Функциональные языки делают упор на выражения. Чисто функциональные языки имеют такие мощные выражения, что операторы могут быть полностью исключены.
Можно ли освободить программирование от стиля фон Неймана? .Императивные языки (Fortran, C, Java, ...) делают упор на операторы для структурирования программ и имеют выражения как своего рода размышления. Функциональные языки делают упор на выражения. Чисто функциональные языки имеют такие мощные выражения, что операторы могут быть полностью исключены.
Можно ли освободить программирование от стиля фон Неймана? .Императивные языки (Fortran, C, Java, ...) делают упор на операторы для структурирования программ и имеют выражения как своего рода размышления. Функциональные языки делают упор на выражения. Чисто функциональные языки имеют такие мощные выражения, что операторы могут быть полностью исключены.