Легкое для понимания объяснение с практическими примерами клиентских транзакций.

Этот пост ни в коем случае не может полностью охватить все аспекты функциональности SQL, однако я пытаюсь создать краткое справочное руководство, в котором представлены практические аспекты SQL и кратко показаны важные функции. Если вы обнаружите какие-либо ошибки, не стесняйтесь их комментировать.

Уровень 1
Выбрать, От, Где, Группировать, Имея, Сортировать по

Когда мы пишем оператор SQL, они должны быть в том же порядке, в каком они написаны выше. Мы также можем увидеть код ниже:

ВЫБРАТЬ *
FROM ‹condition›
WHERE ‹condition›
GROUP BY ‹condition›
ИМЕЕТ ‹condition›
ЗАКАЗ ПО ‹условию›

Однако с точки зрения исполнения поток отличается. Это означает, что когда операторы SQL выполняются на стороне сервера, они читаются в том же порядке, что и написано ниже:

FROM (выбирает необходимую таблицу)
WHERE (фильтрует строки по условию)
GROUP BY (агрегирует результат, который был отфильтрован)
HAVING (дополнительный уровень фильтрации для агрегированные значения)
SELECT (выберите соответствующие столбцы из результата)
ORDER BY (расположите значения по возрастанию или убыванию)

Пример:

SELECT OrderQty, Count(*) AS counts
FROM Sales.SalesOrderDetail
WHERE UnitPrice > 1000
GROUP BY OrderQty
HAVING count(*) < 500
ORDER BY counts desc;

Результат:

Результат показывает, что у нас есть 481 экземпляр заказов с количеством 6, то есть 6 единиц, и 266 экземпляров количества 7 и так далее для всех заказов, у которых цена за единицу превышает 1000. Следовательно, чем выше количество, тем ниже счет.

Уровень 2
Подзапрос, Псевдоним

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

SELECT OrderQty, LineTotal
FROM Sales.SalesOrderDetail AS s1
WHERE UnitPrice = 
(SELECT MIN(UnitPrice) FROM Sales.SalesOrderDetail AS s2
WHERE s1.SalesOrderDetailID = s2.SalesOrderDetailID )

Подзапрос здесь возвращает минимальную цену за единицу для каждого конкретного идентификатора. Итак, если для SalesOrderDetailID из 1 было 5 элементов, он вернет минимальную цену из всех этих 5 элементов, и то же самое для ID 2.

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

Результат

Это означает, что у нас был один экземпляр, в котором количество было равно 1, а общее количество строк составляло 2024,99400 для минимальной цены за единицу, принадлежащей идентификатору. Затем есть еще один экземпляр количества 1 с определенной суммой строки, основанной на минимальной цене.

Уровень 3
В, СУЩЕСТВУЕТ, МЕЖДУ

Предложение IN можно использовать с подзапросами следующим образом:

SELECT FirstName, LastName
FROM Person.Person
WHERE BusinessEntityID IN
       (SELECT BusinessEntityID FROM Sales.SalesPerson
                    WHERE SalesLastYear > 2000000)

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

Предложение EXISTS можно использовать с подзапросом следующим образом:

 SELECT AccountNumber
 FROM Sales.Customer AS c1
 WHERE EXISTS 
(SELECT * FROM Sales.SalesOrderHeader AS SOH
 WHERE SOH.CustomerID = c1.CustomerID AND OnlineOrderFlag=1)

Подзапрос возвращает только логические значения, а не определенные значения, которые могут быть сопоставлены с другими столбцами. Следовательно, всякий раз, когда онлайн-заказ помечен как 1, он возвращает ИСТИНА, а если не ЛОЖЬ. Другими словами, внешний запрос работает только на основе условий ИСТИНА и ЛОЖЬ, предоставленных подзапросом.

Пример МЕЖДУ

SELECT SalesOrderDetailID, UnitPrice FROM Sales.SalesOrderDetail
   WHERE OrderQty BETWEEN 4 AND 6

Он просто проверяет строки с количеством заказов от 4 до 6.

Уровень 4
Оконные функции и операторы регистра

Заявления о случаях действительно крутые.

Это просто инструкция if-then-else. Он проверяет наличие условия и, если оно истинно, возвращает определенное значение, если нет, то перемещается в другую часть. Мы можем определить множество операторов if-then и еще одно выражение. Его можно использовать в любом месте всего скрипта, если он следует правилам SQL.

SELECT  SalesOrderID,
CASE OrderQty
    WHEN 1 THEN 'Order quantity is 1'
    WHEN 2 THEN 'Order quantity is 2'
    WHEN 3 THEN 'Order quantity is 3'
    ELSE 'Greater Than 3'
END AS Order_Quantity
FROM Sales.SalesOrderDetail

В приведенном выше коде просто говорится, что выберите столбец OrderQty и, если он равен 1, напечатайте «количество заказа равно 1» и аналогичным образом сделайте это для других, пока вы не нажмете else, где остальные значения будут напечатаны как «Больше 3».

Оконные функции полезны для сравнения продаж, прибыли и других показателей.

Это снимок реальной таблицы, к которой мы применим оконную функцию.

SELECT OrderQty,
AVG(UnitPrice) OVER(PARTITION BY OrderQty) AS average,
MAX(UnitPrice) OVER(PARTITION BY OrderQty) AS maximum,
MIN(UnitPrice) OVER(PARTITION BY OrderQty) AS minimum FROM
Sales.SalesOrderDetail;

Вот снимок результата.

Уровень 5
Хранимая процедура и IF-ELSE (T-SQL)

Хранимая процедура полезна, когда нам приходится писать фрагмент кода снова и снова. Скорее, мы можем создать хранимую процедуру, определить аргумент, а затем выполнить процедуру с помощью команды EXECUTE. Определяемая нами переменная записывается после @, а затем используется в предложении WHERE.

CREATE PROCEDURE attempt @cost_limit int
      AS
      SELECT * FROM Production.ProductCostHistory
      WHERE StandardCost > @cost_limit and endDate is null
      GO
EXECUTE attempt @COST_LIMIT = 10

Результат дает нам все значения, в которых стандартная стоимость больше, чем значение, переданное переменной cost_limit во время выполнения (в данном случае 10).

Следующий пример

Сначала мы объявляем переменные, затем запускаем оператор IF и проверяем, больше ли количество типов транзакций 1. Если условие истинно, будет выполнен раздел BEGIN. Ключевое слово SET используется для хранения значений оператора select в переменных. После того, как переменные установлены, я использовал оператор печати, чтобы распечатать значения переменных в соответствии с функциональностью конкатенации SQL. Обратите внимание, что функция CAST может быть полезна при преобразовании типа данных переменных.

DECLARE @TYPE1 int
DECLARE @TYPE2 int
DECLARE @TYPE3 int
IF
(SELECT COUNT(*) TransactionType FROM Production.TransactionHistory) > 1
BEGIN
SET @TYPE1 =
(SELECT COUNT(*) FROM Production.TransactionHistory WHERE TransactionType = 'W');
SET @TYPE2 =
(SELECT COUNT(*) FROM Production.TransactionHistory WHERE TransactionType = 'S');
SET @TYPE3 =
(SELECT COUNT(*) FROM Production.TransactionHistory WHERE TransactionType = 'P');
PRINT 'Total count of W type transactions ' + CAST(@type1 as varchar(10)) + '.' ;
PRINT 'Total count of s type transactions ' + CAST(@type2 as varchar(10)) + '.' ;
PRINT 'Total count of p type transactions ' + CAST(@type3 as varchar(10)) + '.' ;
END

Дополнительный запрос, который использует как хранимую процедуру, так и функцию IF-ELSE для вывода результата.

CREATE PROCEDURE Learning
@quantity int,
@cost INT
AS
BEGIN
DECLARE @COUNT INT
SET @COUNT =
(SELECT count(*) from Production.TransactionHistory where Quantity > @quantity and actualcost > @cost)
PRINT @COUNT
IF @count > 1000
BEGIN
PRINT 'There are more than 1000 instances with quantity =' + cast(@quantity as varchar)+ ' and cost =' + + cast(@cost as varchar)
END
ELSE
BEGIN
PRINT 'THERE ARE LESS THAN 1000 such INSTANCES'
END
END
GO
EXECUTE Learning @COST=10 , @QUANTITY = 10

Обратите внимание на некоторые важные моменты

  • EXISTS зависит от логических значений, выводимых подзапросом.
  • IN зависит от совпадающих значений, выводимых подзапросом.
  • Порядок предложений имеет значение в SQL и зависит от порядка выполнения.
  • Переменные, определенные для хранимых процедур, отличаются от объявленных.
  • Все что угодно может быть помещено между BEGIN и END и запущено как единый пакет.