Начальный раздел SQL: избегание повторного выражения

Я полностью новичок в SQL, но, скажем, в Проводнике данных StackExchange я просто хочу перечислить 15 лучших пользователей по репутации, и я написал что-то вроде этого:

SELECT TOP 15
  DisplayName, Id, Reputation, Reputation/1000 As RepInK
FROM
  Users
WHERE
  RepInK > 10
ORDER BY Reputation DESC

В настоящее время это приводит к Error: Invalid column name 'RepInK', что, я думаю, имеет смысл, поскольку RepInK не является столбцом в Users. Я легко могу это исправить, сказав WHERE Reputation/1000 > 10, по сути повторяя формулу.

Итак, вопросы:

  • Могу ли я на самом деле использовать RepInK "столбец" в WHERE?
    • Возможно, мне нужно создать виртуальную таблицу/представление с этим столбцом, а затем выполнить запрос SELECT/WHERE?
  • Могу ли я назвать выражение, например, Reputation/1000, чтобы мне пришлось повторять имена только в нескольких местах вместо формулы?
    • Как вы это называете? Макрос подстановки? Функция? Хранимая процедура?
  • Есть ли таблица SQL-запросов, глоссарий терминов, спецификация языка, что-нибудь, что я могу использовать, чтобы быстро понять синтаксис и семантику языка?
    • Я так понимаю, что есть разные "ароматы"?

Ответ 1

Могу ли я использовать столбец RepInK в предложении WHERE?

Нет, но вы можете быть уверены, что ваша база данных будет оценивать (Reputation / 1000) один раз, даже если вы используете ее как в полях SELECT, так и в предложении WHERE.

Возможно, мне нужно создать виртуальную таблицу/представление с этим столбцом, а затем выполнить запрос SELECT/WHERE?

Да, представление является одним из вариантов упрощения сложных запросов.

Могу ли я назвать выражение, например. Репутация /1000, поэтому мне нужно только повторять имена в нескольких местах вместо формулы?

Вы можете создать определенную пользователем функцию, которую вы можете вызвать как convertToK, которая получит значение rep в качестве аргумента и возвращает этот аргумент, деленный на 1000. Однако это часто бывает непрактичным для тривиального случая, подобного одному в вашем примере.

Есть ли SQL-лист SQL, глоссарий терминов, спецификация языка, все, что я могу использовать, чтобы быстро подобрать синтаксис и семантику языка?

Я предлагаю практику. Вы можете начать использовать тег mysql для, где каждый день задают много начинающих вопросов. Загрузите MySQL, и когда вы подумаете, что есть вопрос, который вам подходит, попытайтесь найти решение. Я думаю, что это поможет вам получить скорость, а также понимание особенностей языков. Не нужно сначала публиковать ответ, потому что здесь есть довольно быстрые пушки, но с некоторой практикой я уверен, что вы сможете принести домой несколько моментов:)

Я понимаю, что существуют разные "ароматы"?

Ароматизаторы на самом деле являются расширениями ANSI SQL. Производители баз данных обычно добавляют язык SQL с расширениями, такими как Transact-SQL и PL/SQL.

Ответ 2

Вы можете просто переписать предложение WHERE

where reputation > 10000

Это не всегда будет удобно. Как альтернативно, вы можете использовать встроенный просмотр:

SELECT
  a.DisplayName, a.Id, a.Reputation, a.RepInK 
FROM 
   (
        SELECT  TOP 15  
          DisplayName, Id, Reputation, Reputation/1000 As RepInK 
        FROM 
          Users 
        ORDER BY Reputation DESC 
    ) a
WHERE 
  a.RepInK > 10 

Ответ 3

Что касается именованных выражений, в то время как существует несколько возможных альтернатив, оптимизатор запросов будет лучше всего использовать формулу Reputation / 1000 long-hand. Если вам действительно нужно запустить целую группу запросов с использованием одного и того же оцененного значения, лучше всего создать представление с заданным полем, но вы не захотите делать это для одноразового запроса.

В качестве альтернативы (и в тех случаях, когда производительность не является большой проблемой), вы можете попробовать что-то вроде:

SELECT TOP 15
    DisplayName, Id, Reputation, RepInk
FROM (
     SELECT DisplayName, Id, Reputation, Reputation / 1000 as RepInk
     FROM Users
) AS table
WHERE table.RepInk > 10
ORDER BY Reputation DESC

хотя я не верю, что поддерживается всеми диалектами SQL, и, опять же, оптимизатор, скорее всего, сделает гораздо худшую работу, подобную этой вещи (так как она будет запускать SELECT в отношении полной таблицы Users, а затем фильтровать ее результат). Тем не менее, для некоторых ситуаций такой запрос подходит (есть имя для этого... Я рисую пробел в данный момент).

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

Хотя SQL является "стандартизированным", к сожалению (хотя, в некоторой степени, к счастью), каждый поставщик базы данных реализует свою собственную версию с собственными расширениями, что может привести к тому, что наиболее подходящий синтаксис является наиболее подходящим (для обсуждения несовместимости различных баз данных по одному вопросу см. в документации SQLite для обработки NULL. В частности, стандартные функции, например, для обработки DATE и TIME, отличаются друг от друга, и есть другие, более резкие отличия (в частности, в подзапросах без поддержки или правильном обращении с JOIN). Если вы интересуетесь некоторыми деталями, this документ предоставляет как стандартные формы, так и отклонения для нескольких основных баз данных.

Ответ 4

Вы CAN ссылаетесь на RepInK в предложении Order By, но в предложении Where вы должны повторить выражение. Но, как говорили другие, он будет выполнен только один раз.

Ответ 5

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

Если вы просто работаете с DataExplorer, вам нужно будет ознакомиться с синтаксисом SQL Server, так как это работает. Лучшее место, чтобы найти это, конечно, ссылка MSDN.

Да, существуют различные варианты синтаксиса SQL. Например, предложение TOP в запросе, которое вы указали, является специфичным для SQL Server; в MySQL вы должны использовать предложение LIMIT вместо этого (и эти ключевые слова не обязательно отображаются в одном и том же месте в запросе!).