Претражи овај блог

среда, 16. јун 2010.

Основна SELECT нарeдба

Наредба SELECT је камен темељац T-SQL језика. У следећим примјерима ћу показати врло једноставну употребу те наредбе над AdventureWorks базом података.
Примјер:

-- улаз у базу података
USE AdventureWorks
GO
-- дефинишем које ће се колоне приказати у упиту
SELECT NacionalIDNamber,LoginID,JobTitle
-- дефинишем табелу из које се подаци приказују
FROM HumanResources.Employee
Уколико желите приказати све колоне из извора података у FROM клаузули, користите следећи упит.
Примјер:
'Улаз у базу података
USE AdventureWorks
GO
'дефинишем приказ свих колона из табеле, симбол (*) приказује све колоне и редове из табеле
SELECT *
FROM HumanResorces.Employee
У SELECT упиту, WHERE клаузула се користи за ограничавање приказа колона из скупа резултата. Следећи примјер показује како одабрати само неке редове из колона који ће бити приказане у скупа података.
Примјер:
'дефинишем колоне које ће бити приказане у скупу резултата
SELECT Title, FirstName, LastName
FROM Person.Person
' услов, само оне колоне гдје је ( Title='Ms.')
WHERE Title='Ms.'
У наредном примјеру ћу показати како се преко логички оператора (AND,OR,NOT) могу претраживати услови у скупу резултата
Примјер:
SELECT Title,FirstName,LastName
FROM Person.Person
--услов (Title='Mr.' And LastName='Radenko')
WHERE Title='Mr.' AND LastName='Radenko'
Примјер:
SELECT Title,FirstName,LastName
FROM Person.Person
--услов (Title='Mr.' Or LastName='Radenko')
WHERE Title='Mr.' OR LastName='Radenko'
Примјер:
SELECT Title,FirstName,LastName
FROM Person.Person
--услов (NOT Title='Mr.' )
WHERE NOT Title='Mr.'

Следећи примјер демонстрира коришћење BETWEEN оператора тј, иѕбор између.

Примјер:
SELECT SalesOrderID,ShipDate
FROM Sales.SalesOrderHeader
-услов, између два датума
WHERE ShipDate BETWEEN '7/28/2010 AND '9/28/2010'

Употреба оператора поређења < (мање од)
У следећем примјеру демонстрирати ћу оператор (мање од), и приказати само оне колоне чији је стандардни трошак мањи од 110.0000

Примјер:
-дефинишем колоне које ћу приказати у скупу резултата
SELECT ProductID,Name,StandardCost
FROM Production.Product
-постављам услов, за све вриједности чији је стандардни трошак мањи од
WHERE StandardCost <> 110.0000

Провјера за NULL вриједности
Ако колона има NULL вриједност то не значи да је вриједност празна или нула него да је вриједност непозната. Следећи примјер враћа редове из скупа резултата чија је вриједност непозната.


Примјер:
SELECT ProductID,Name,Weight
FROM Production.Product
--услов да је тежина непозната
WHERE Weight IS NULL

Употреба замјенских знакова са оператором LIKE
Ови знакови се користе у изразима за претраживанје да би сте пронашли одговарајући узорак унутар претраге. Ово су ти знакови (% представља низ од више знакова или нула, _ представљ један знак, [] одређује један знак из одабраног распона, [^] одређује један знак који није у одабраном распону). Следећи примјер демонстрира употребу LIKE оператора са знаком % у потрази за било којим производом који почиње са словом Б.

Примјер:
SELECT ProductID,Name
FROM Production.Product
--услов, пронађи било који производ који почиње са словом Б
WHERE Name LIKE 'B%'

Ако желите претраживати дословне вриједности са знаковима (%,_) онда морате користити ESCAPE оператор. У наредом примјеру ћу прво измејенити ред опис у табели производи додавајући знак %.

Пример:
UPDATE Production.ProductDescription
SET Description = 'Chromoly steel. High % of defects'
WHERE ProductDescriptionID = 3

Даље, дефинисати ћу упит у потрази ѕа било каквим описом који садржи знак %

Примјер:
SELECT ProductDescriptionID,Description
FROM Production.ProductDescription
--услов, пронађи опис који у себи садржи знак %
WHERE Description LIKE '%/%%' ESCAPE '/'

Дефинисања и додјељивање вриједности промјенљивима
Промјенљиве су објекти које можете направити како би у њих привремено похрањивали податке. Оне могу бити дефинисане преко неколико типова података. У наредном примјеру видјети ће те два различита примјера за дефинисање и додјељивање вриједности промјенљивима:

Примјер:
--прво дефинишем пром.
DECLARE @AddressLine nvarchar(60)
--затим додјељујем вриједност
SET @AddressLine = 'Radenko'

SELECT AddressID, AddressLine
FROM Person.Address
--услов, у колони пронађи додј.вриједност
WHERE AddressLine LIKE '%' + @AddressLine + '%'

Ново у SQL Serveru 2008 је то што можете уклонити SET инструкцију.

Примјер:
--значи одмах дефинишем и додјељујем вриједност
DECLARE @AddressLine nvarchar(60) = 'Radenko'
SELECT AddressID, AddressLine
FROM Person.Address
WHERE AddressLine LIKE '%' + @AddressLine + '%'

Груписање података GROUP BY
GROUP BY клаузула се користи у SELECT изразу ради одређивања група или скупина редova у скупу резултата. GROUP BY слиједи послије WHERE клаузуле и најчеше се користи када користимо агрегатне функције у SELECT изразу. Следећи примјер користи клаузулу GROUP BY да би груписао укупан износ потраживанја продаје по датуму продаје.

Примјер:
SELECT OrderDate,SUM(TotalDue) TotalDueByOrderDate
FROM Sales.SalesOrderHeader
WHERE OrderDate BETWEEN '1/1/2010' AND '1/31/2010'
--вршим груписање по датуму продаје
GROUP BY OrderDate

Коришћење GROUP BY ALL
Овом наредбом се групишу сви редови чак и ако ниси наведени у WHERE клаузули. Следећи примјер је исти као и предхотни стим што је укључена ALL клаузула.

Примјер:
SELECT OrderDate,SUM(TotalDue) TotalDueByOrderDate
FROM Sales.SalesOrderHeader
WHERE OrderDate BETWEEN '1/1/2010' AND '1/31/2010'
--групишем по свим колонама
GROUP BY ALL OrderDate

Селективно претраживање груписања података употребом HAVING клаузуле
Ова калузула вам омогућава да у SELECT изразу обавите претраживање помоћу GROUP BY и/или групне вриједности. Следећи примјер поставља упит на двије табеле, Production.ScrapReason и Production.WorkOrder. Прва табела Production.ScrapReason садржи производни неуспјех док друга табела садржи налоге производње који контролишу рад који производи се производе у одређеном временском раздобљу како би се дефинисале продајне потребе предузећа. Следећи примјер извјештава управу који су то "неуспјели разлози" који су се догодили 50 или више пута.

Примјер:
SELECT s.Name, COUNT(w.WorkOrderID) Cnt
FROM Production.ScrapReason s
INNER JOIN Production.WorkOrder w ON s.ScrapReasonID = w.ScrapReasonID
GROUP BY s.Name
--пребројавм све неуспјеле разлоге веће или једнаке 50
HAVING COUNT(*)>50

Редослијед резултата ORDER BY
Ова клаузула дефинише редослијед приказа података на темљу одређених колона или израза. Следећи примјер демонстрира упит који дефинише редослијед приказа по колонама
ProductID и EndDate:

Примјер:
SELECT p.Name,h.EndDate,h.ListPrice
FROM Production.Product p
INNER JOIN Production.ProductListPriceHistory h ON p.ProductID = h.ProductID
--деф.редос.по овим колонама
ORDER BY p.Name, h.EndDate

Подразумјевани редослијед података за ову клузулу је у растућем ASC редослиједу. У следећем примјеру ћу демострирати DESC (опадајући) tj. дa се врати резултат у опадајућем редoслиједу.

Примјер:
SELECT p.Name,h.EndDate,h.ListPrice
FROM Production.Product p
INNER JOIN Production.ProductListPriceHistory h ON p.ProductID = h.ProductID
--деф.опадајући редослијед по задатим колонама
ORDER BY p.Name DESC, h.EndDate DESC

Употреба TOP кључне ријечи са ORDER BY клаузулом
Ова кључна ријеч вам омогућава да вратите први н-редова из упита на основу броја редова или процента редова које дефинишете. У наредном примјеру првих 10 редова се преузимају иѕ табеле Purchasing.Vendor за оне редове са највећом вриједношћу из колоне CreditRating:

Примјер:
--приказујем првих 10
SELECT TOP 10 v.Name,v.CreditRating
FROM Purchasing.Vendor v
ORDER BY v.CreditRating DESC, v.Name

У следећем примјеру демонстрирам број редова враћених преко процента коришћељем промјењивих:

Примјер:
DECLARE @Percentage float
SET @Percentage = 1
--узимам промјењиву у којој је дефинисана вриједност процента
SELECT TOP (@Percentage) PERCENT Name
FROM Production.Product
ORDER BY Name

Коришћење DISTINCT израза ѕа уклањање дупли редова
DISTINCT израз враћа само јединствене редове из скупа резултата. Следећи примјер враћа само јединствене редове из табеле HumanResources.Employee.

Примјер:
SELECT DISTINCT HireDate
FROM HumanResources.Employee

Коришћење DISTINCT израза у агрегатним функцијама
То је потребно како би смо добили агрегацију само јединствених вриједности у скупу резултата нпр. ако би смо хтјели да израчунамо просјечну цијену производа тј.

Примјер:
--користим агрегатну функцију за рачунање просјечне цијене
SELECT AVG(ListPrice)
FROM Production.Product

Овај упит израчунава просјечну цијену за све производе, а шта ако су неки производи бројнији од других, а нама је потребна јединствена просјечна цијена у том случају слиједи:

Примјер:
--прво издвајамо јединстве цијене а затим рачунам просјечну цијену
SELECT AVG(DISTINCT ListPrice)
FROM Production.Product

Коришћење колоне ALIASES
За израчунату колону или агрегатну функцију, можете да користите псеудоним колоне експлицитно име колоне. Следећи примјер демонстрира креиранје колона ALIASES користећи двије различите технике;

Примјер:
--први примјер показује како се преименује колона коришћенјем АS кључне ријечи
SELECT Color AS 'Grouped Color',AVG(DISTINCT ListPrice) AS 'Average Distinct List Price',
--овдје додајем псеудоним колони без употребе кључне ријечи АS
AVG(ListPrice) 'Average List Price'
FROM Production.Product
GROUP BY Color
Употреба SELECT израза за креирање скрипти
Као програмер или администратор базе података, потребно је да знате креирати T-SQL скрипте које вам у многоме олакшавају рад над базом податка. На примјер имате веома велику табелу са неколико колона и требате за саваку колону дефинисати неки услов, али не желите ручно одређивати сваки тип колоне умјесто тога можете направити скрипту да ради за вас.
Примјер:
SELECT column_name + ' IS NULL AND '
FROM INFORMATION_SCHEMA.columns
WHERE table_name = 'Employee'
ORDER BY ORDINAL_POSITION
Примјер користи скрипт за спајање INFORMATION_SCHEMA.columns у циљу генерисања списка колона из табеле запослених за сваку колону која је IS NULL AND
Коришћење (+) оператора за спајње
Овај оператор служи за спајање израза. У следећем примјеру ћу демонстрират његову употребу.
Примјер;
--користим (+) за спајање ових израза или колона у једну колону
SELECT 'The ' +p.name +' is only ' +CONVERT(varchar(25),p.ListPrice) +'!'
FROM Production.Product p
WHERE p.ListPrice between 100 AND 120
ORDER BY p.ListPrice
Креирање низова -листа раздвојених зарезом преко команде SELECT
Следећи примјер враћа податке из табеле (један-према-више) у облику низа.
Примјер:
--прво дефинишем промјењљиви и иницијализујем је као празну
DECLARE @Shifts varchar(20) = ''
--затим промјенљивој додјељујем вриједност колоне с.Наме и зарез
SELECT @Shifts = @Shifts + s.Name + ','
FROM HumanResources.Shift s
ORDER BY s.EndTime
--SELECT користим за коначни приказ садржаја промјњ.
SELECT @Shifts
Употреба INTO клаузуле
SELECT израз наm омогућава креирање нове табеле на основу резултата упита.
Примјер:
SELECT BusinessEntityID,Name,SalesPersonID,Demographics
--правим нову табелу Store_Archive али у њу убацујем само број редова а не резултат упита
INTO Store_Archive
FROM Sales.Stor
У наредном примјеру креирам нову табелу без убацивања броја редова
Примјер:
SELECT BusinessEntityID,Name,SalesPersonID,Demographics
--креирам нову табелу
INTO Store_Archive_2
FROM Sales.Store
--услов, без убацивања редова тј. број 1 никада неће бити једнак нули
WHERE 1=0
Креирање ПОДУПИТА
Подупит је SELECT упит у којем су угнијежђени други SELECT, INSERT,UPDATE или DELETE израз. У првом примјеру ћу извршити провјеру постојања редова у корелацији подупита.
Примјер:
USE AdventureWorks
GO
--издвоји јединствне редове
SELECT DISTINCT s.PurchaseOrderNumber
FROM Sales.SalesOrderHeader s
--дефинишем подупит и постављам услов
WHERE EXISTS ( SELECT SalesOrderID
FROM Sales.SalesOrderDetail
--uslov који су то произ.са јединичном цијеном 1000 и 2000 у подупиту
WHERE UnitPrice BETWEEN 1000 AND 2000 AND SalesOrderID = s.SalesOrderID)
GO
У другом примјеру ћу показати неповезани подупит.
Примјер:
SELECT BusinessEntityID,SalesQuota АS CurrentSalesQuota
FROM Sales.SalesPerson
--само продавци који су имали максималну продајну квоту
WHERE SalesQuota =(SELECT MAX(SalesQuota)
FROM Sales.SalesPerson)
GO
Претраживање из више извора података
INNER -придружене кључне ријечу вам омогућавају да комбинујете податке из више табела у један скуп резултата. Придружене колоне не морају да имају исто име него само да су им типови података компатибилни. У следећем примјеру ћу придружити или спојити три табеле како би добио повратну информацију о попусту на одређени производ.
Примјер:
SELECT p.Name,s.DiscountPct
--прва табела
FROM Sales.SpecialOffer s
--спајам прву и другу табелу
INNER JOIN Sales.SpecialOfferProduct o ON s.SpecialOfferID = o.SpecialOfferID
--спајам другу и трећу табелу
INNER JOIN Production.Product p ON o.ProductID = p.ProductID
--издвајам назив производа из треће табеле
WHERE p.Name = 'All-Purpose Bike Stand'
Употреба OUTER (спољног) спајања
Следећи примјер упоређује резултате INNER JOIN (унутрашњег спајање) наспрам LEFT OUTER JOIN (лијево вањског спајање), овај први упит показује пореске стопе држава и покрајина користећи двије табеле и унутрашње спајање.
Примјер:
SELECT s.CountryRegionCode,s.StateProvinceCode,t.TaxType,t.TaxRate
FROM Person.StateProvince s
--користим унутршњо спајање табела
INNER JOIN Sales.SalesTaxRate t ON s.StateProvinceID = t.StateProvinceID
А овај други упит користи лијево спољашње спајање:
Примјер:
SELECT s.CountryRegionCode,s.StateProvinceCode,t.TaxType,t.TaxRate
FROM Person.StateProvince s
--лијево спољашње спајање табела
LEFT OUTER JOIN Sales.SalesTaxRate t ON s.StateProvinceID = t.StateProvinceID
Коришћење CROSS спајања
Ово спајање без WHERE калузуле даје декартов производ.
Примјер:
SELECT s.CountryRegionCode,s.StateProvinceCode,t.TaxType,t.TaxRate
--из ове табеле добијем 181 ред а из друге табеле 29 редова
FROM Person.StateProvince s
--декартов производ 181 * 29 =5249 редова у резултату, не коритистим WHERE
CROSS JOIN Sales.SalesTaxRate t
Референцирање једне табеле више пута у исти упит
Понекада ће те рефернцирати исту табелу на основу различити временских периода нпр. поређење продаје из 2009 у 0дносу на 2010 годину. Да би сте спојили табелу саму са собом то можете извести помоћу тебеле псеудонима. У следећем примјеру табела Sales.SalesPersonQuotaHistory је два пута неведена у FROM калузулу, са једним позивом из 2004 и другим позивом из 2003 године:
Примјер:
SELECT s.BusinessEntityID,SUM(s2004.SalesQuota) Total_2004_SQ,
SUM(s2003.SalesQuota) Total_2003_SQ
FROM Sales.SalesPerson s
-у овом лијевом вањском спајању, користим псеудоним (s2004)
LEFT OUTER JOIN Sales.SalesPersonQuotaHistory s2004 ON
s.BusinessEntityID = s2004.BusinessEntityID AND YEAR(s2004.QuotaDate)= 2004
-у овом лијевом вањском спајању, користим псеудоним (s2003)
LEFT OUTER JOIN Sales.SalesPersonQuotaHistory s2003 ON
s.BusinessEntityID = s2003.BusinessEntityID AND YEAR(s2003.QuotaDate)= 2003
GROUP BY s.BusinessEntityID
Употреба изведених табела
Овај примјер показује како се користе изведене табеле у FROM клаузули SELECT израза.
Примјер:
SELECT DISTINCT s.PurchaseOrderNumber
FROM Sales.SalesOrderHeader s
-придружујем изведену табелу користећи INNER JOIN, изведена табела је посебан упит и не захтијева употребу привремене табеле што даје добре резултате у извршењу
INNER JOIN (SELECT SalesOrderID FROM Sales.SalesOrderDetail
-издвајам било који налог који садржи производе са јединичном цијеном између 1000 и 2000
WHERE UnitPrice BETWEEN 1000 AND 2000) d ON s.SalesOrderID = d.SalesOrderID
Конбиновање резултата скупова са UNION (унијом)
UNION оператор се користи да додате резултате два или више SELECT израза у један скуп резултата. Да би се SELECT изрази спојили морају да имају исти број колона са истим или компатибилним типовима података.
Примјер:
-исти број колона тј.3
SELECT BusinessEntityID, GETDATE() QuotaDate, SalesQuota
FROM Sales.SalesPerson
-услов продајна кота већа од нуле
WHERE SalesQuota > 0
-дефинишем унију два SELECT израза
UNION
-исти број колона тј.3
SELECT BusinessEntityID, QuotaDate, SalesQuota
FROM Sales.SalesPersonQuotaHistory
-услов, продајна квота већа од нуле
WHERE SalesQuota > 0
ORDER BY BusinessEntityID DESC, QuotaDate DESC
Употреба CROSS APPLY
Овај израз је сличан изразу INNER JOIN. У следећем примјеру дефинишем корисничко дефинисану финкцију која враћа резултат у табелерном облику тј. информацију о радном налогу на основу WorkOrderID односно редног броја налога.
Примјер:
--деф.функцију и прослеђујем параметар @WorkOrderID
CREATE FUNCTION dbo.fn_WorkOrderRouting
--деф.улазну промјњиву
(@WorkOrderID int) RETURNS TABLE
AS
RETURN
SELECT WorkOrderID,ProductID,OperationSequence,LocationID
FROM Production.WorkOrderRouting
--uslov, da je redni broj naloga jednak ulaznom paramteru
WHERE WorkOrderID = @WorkOrderID
GO
--затим, тај редни број налога прелази у нову функцију
SELECT w.WorkOrderID,w.OrderQty,r.ProductID,r.OperationSequence
FROM Production.WorkOrder w
CROSS APPLY dbo.fn_WorkOrderRouting(w.WorkOrderID) AS r
ORDER BY w.WorkOrderID,w.OrderQty,r.ProductID
Да објасним, прво креирам функцију која враћа табеларну вриједност, та функција прихвата један улазни параметар, и када се изврши враћа резултат у табеларном облику и то са следећим редовима WorkOrderID, ProductID,OperationSequence, и LocationID из табеле Production.WorkOrderRouting за редни број налога који сам навео у улазном параметру. Затим дефинишем нови упит у који прослеђујем реднe бројeвe налога преко корисничко дефинисане функције из табеле Production.WorkOrderRouting . Ако сте примјетили да у FROM клаузули табелу Production.WorkOrder спајам са функцијом коју сам раније дефинисао и то са кључном ријечи CROSS APPLY и кроз ту функцију прихватам редне бројеве налога из прве табеле Production.WorkOrderRouting те као резултат добијам скуп који само има редове са тим бројевима радних налога.
Употреба OUTER APPLY израза
У наредном примјеру ћу демонстрирати овај израз, прво ћу наредбом INSERT убацити нови ред у табелу Production.WorkOrder. Ова тебела има колону типа IDENTITY па ће према томе колона WorkOrderID имати максималну вриједност.
Примјер:
INSERT INTO [AdventureWorks].[Production].[WorkOrder]
([ProductID],[OrderQty],[ScrappedQty],[StartDate],[EndDate],[DueDate],[ScrapReasonID],[ModifiedDate])
VALUES(1,1,1,GETDATE(),GETDATE(),GETDATE(),1,GETDATE())
Затим ћу преко новог упита искористити израз OUTER APPLY и као резултат добити скуп који садржи ред који сам убацио у предходном примјеру.
Примјер:
SELECT w.WorkOrderID,w.OrderQty,r.ProductID,r.OperationSequence
FROM Production.WorkOrder AS w
--код овог спајања не добијам ни један ред, јер на лијевој старни табеле намам премца
CROSS APPLY dbo.fn_WorkOrderRouting(w.WorkOrderID) AS r
WHERE w.WorkOrderID IN (SELECT MAX(WorkOrderID) FROM Production.WorkOrder)
Примјер:
SELECT w.WorkOrderID,w.OrderQty,r.ProductID,r.OperationSequence
FROM Production.WorkOrder AS w
--код овог спајања добијам тај нови ред у резултату,без обзира што не постоји повезана вриједност у табели.
OUTER APPLY dbo.fn_WorkOrderRouting(w.WorkOrderID) AS r
WHERE w.WorkOrderID IN (SELECT MAX(WorkOrderID)FROM Production.WorkOrder)
Употреба TABLESAMPLE израза
Овај израз вам омогућава да издвојите из FROM клаузуле само редове на основу неког узорка. Тај узорак може бити проценат.
Примјер:
SELECT ContactID,FirstName
FROM Person.Contact
--издвајам само 2 посто од укупног броја редова
TABLESAMPLE SYSTEM (2 PERCENT)
Употреба PIVOT оператора
Овај израз вам омогућава да креирате cross-tab (унакрсне упите) који претварају вриједности у колони, користећи агрегацију за групу података од стране нове колоне.
Следећи примјер показује смјене запослених као и одјељења у којима се налазе.
Примјер:
SELECT s.Name Smjena,d.Name Odjeljenje
FROM HumanResources.EmployeeDepartmentHistory h
INNER JOIN HumanResources.Department d ON h.DepartmentID = d.DepartmentID
INNER JOIN HumanResources.Shift s ON h.ShiftID = s.ShiftID
--да ЕндДате није Нулл и да се смјена налази у неком у одјељења
WHERE EndDate IS NULL AND d.Name IN ('Production', 'Engineering', 'Marketing')
ORDER BY Smjena
У наредном упиту користим PIVOT оператор да би направио агрегацију вриједности на спојеним табела и као резултат диобио следеће колоне (ShiftName,Production,Engineering,Marketing)
Примјер:
SELECT ShiftName,Production,Engineering,Marketing
--из FROM клаузуле позивам подупит који спаја двије табеле
FROM (SELECT s.Name ShiftName,h.DepartmentID,d.Name DepartmentName
FROM HumanResources.EmployeeDepartmentHistory h
INNER JOIN HumanResources.Department d ON h.DepartmentID = d.DepartmentID
INNER JOIN HumanResources.Shift s ON h.ShiftID = s.ShiftID
--услов да ЕндДате није нулл вриједност и да се смјена налази у једном од одјељења
WHERE EndDate IS NULL AND d.Name IN ('Production', 'Engineering', 'Marketing')) AS a
--опратор PIVOT и правим агрегацију вриједности кроз унакрсно спајање табела
PIVOT
(
--пребројавам
COUNT(DepartmentID)
FOR DepartmentName IN ([Production], [Engineering], [Marketing])
) AS b
ORDER BY ShiftName
Употреба UNPIVOT израза
Овај израз ради супротно од PIVOT израза и претвара колоне у редове. У следећем примјеру ћу прво направити табелу dbo.Contact, затим ћу унјети редни број запосленог, телефон1, телефон2 и телефон3.
Примјер:
CREATE TABLE dbo.Contact
(EmployeeID int NOT NULL,
PhoneNumber1 bigint,
PhoneNumber2 bigint,
PhoneNumber3 bigint)
GO
--уносим податке у први ред табеле
INSERT dbo.Contact
(EmployeeID, PhoneNumber1, PhoneNumber2, PhoneNumber3)
VALUES( 1, 2718353881, 3385531980, 5324571342)
--уносим податке у други ред табеле
INSERT dbo.Contact
(EmployeeID, PhoneNumber1, PhoneNumber2, PhoneNumber3)
VALUES( 2, 6007163571, 6875099415, 7756620787)
--уносим податке у трећи ред табеле
INSERT dbo.Contact
(EmployeeID, PhoneNumber1, PhoneNumber2, PhoneNumber3)
VALUES( 3, 9439250939, NULL, NULL)
Затим ћу у другом упиту, преко UNIPIVOT израза претворити те колоне у редове
Примјер:
SELECT EmployeeID,PhoneType,PhoneValue
FROM (SELECT EmployeeID, PhoneNumber1, PhoneNumber2, PhoneNumber3 FROM dbo.Contact) c
UNPIVOT
(PhoneValue FOR PhoneType IN ([PhoneNumber1], [PhoneNumber2], [PhoneNumber3])
) AS p
Употреба EXCEPT и INTERSECT израза за поврат јединствених или усклађених података
Ако је потребно да упоредите редове између двију табела, нпр. редове који су постојали у једној тебели а не у другој. Ова два израза су корисна за пренос података, опоравак података, јер можете да вратите базу података из периода прије губитка података.
У следећем примјеру прво ћу креирати двије табеле А и Б које со настале из табеле Production.Product а затим ћу демонстирати ова два израза.
Примјер:
SELECT prod.ProductID,prod.Name
--креирам табелу А
INTO dbo.TableA
FROM (SELECT ProductID,Name,ROW_NUMBER() OVER (ORDER BY ProductID) RowNum
--узимам колоне из
FROM Production.Product) prod
--само првих 20 редова
WHERE RowNum BETWEEN 1 and 20
Примјер:
SELECT prod.ProductID,prod.Name
--креирам табелу Б
INTO dbo.TableB
FROM (SELECT ProductID,Name,ROW_NUMBER() OVER (ORDER BY ProductID) RowNum
--узимам колоне
FROM Production.Product) prod
--услов
WHERE RowNum BETWEEN 10 and 29
Примјер:
SELECT ProductID,Name
FROM dbo.TableA
--враћам само јединствене редове из ових табела
INTERSECT
SELECT ProductID,Name
FROM dbo.TableB
Примјер:
SELECT ProductID,Name
FROM dbo.TableA
--упоређујем ове табеле, то јесте који редови постоје само у лијевој табели А а не у табели Б
EXCEPT
SELECT ProductID,Name
FROM dbo.TableB
Употреба COUBE израза
Овај израз сумира укупне вриједности на основу колона у GROUP BY клаузули. У следећем примјеру ћу као резултат вратити укупну количину производа који су груписани по полицама и локацијама на којима се чувају. Неке истанце сервера не подржавају овај израз.
Примјер:
SELECT i.Shelf,i.LocationID, SUM(i.Quantity) Total
FROM Production.ProductInventory i
GROUP BY CUBE (i.Shelf,i.LocationID)
Употреба GROUPING SETS израза (ново у SQL Serveru 2008)
У предходним верзијама сервера приликом груписања резултата из више табела смо користили UNION ALL, у SQL Serveru 2008 сада користим нови израз GROUPING SETS који има исту функцију као израз UNION ALL. У првом примјеру ћу демонстрирати стари израз UNION ALL.
Примјер:
SELECT NULL,i.LocationID,p.Name,SUM(i.Quantity) Total
FROM Production.ProductInventory i
INNER JOIN Production.Product p ON i.ProductID = p.ProductID
WHERE Shelf IN ('A','C') AND Name IN ('Chain', 'Decal', 'Head Tube')
GROUP BY i.LocationID, p.Name
--креирам унију
UNION ALL
SELECT i.Shelf,NULL,NULL,SUM(i.Quantity) Total
FROM Production.ProductInventory i
INNER JOIN Production.Product p ON i.ProductID = p.ProductID
WHERE Shelf IN ('A','C') AND Name IN ('Chain', 'Decal', 'Head Tube')
GROUP BY i.Shelf
--креирам унију
UNION ALL
SELECT i.Shelf,NULL,p.Name,SUM(i.Quantity) Total
FROM Production.ProductInventory i
INNER JOIN Production.Product p ON i.ProductID = p.ProductID
WHERE Shelf IN ('A','C') AND Name IN ('Chain', 'Decal', 'Head Tube')
GROUP BY i.Shelf, p.Name
Примјер:
SELECT i.Shelf,i.LocationID,p.Name,SUM(i.Quantity) Total
FROM Production.ProductInventory i
INNER JOIN Production.Product p ON i.ProductID = p.ProductID
WHERE Shelf IN ('A','C') AND Name IN ('Chain', 'Decal', 'Head Tube')
--овај израз вам омогућава да одредите различите агрегатне групе у једном упиту,
--избјегавајући коришћење вишеструки упита и то у само 2 линије кода.
GROUP BY GROUPING SETS
((i.Shelf), (i.Shelf, p.Name), (i.LocationID, p.Name))
Употреба (CTE-Common Table Expression) израза
CTE је приврмени скуп резултата изведен из једноставних упита и дефинисан у оквиру извршења наредби SELECT, INSERT, UPDATE, или DELETE. У наредном примјеру користим нерекурзивни CTE зато што подаци нису придружени сами себи, него из УНИЈЕ два скупа података.
Примјер:
--деф.привремни скуп и колоне које ћу приказати
WITH VendorSearch (RowNumber, VendorName, AccountNumber)
AS
--из ове табеле на основу УНИЈЕ из два подскупа узимам првих пет и задњи пет резултата
(
SELECT ROW_NUMBER() OVER (ORDER BY Name) RowNum,Name,AccountNumber
FROM Purchasing.Vendor
)
SELECT RowNumber,VendorName,AccountNumber
FROM VendorSearch
--првих пет по имену
WHERE RowNumber BETWEEN 1 AND 5
UNION
SELECT RowNumber,VendorName,AccountNumber
FROM VendorSearch
--посљедњих пет по имену
WHERE RowNumber BETWEEN 100 AND 104
У следећем примјеру ћу демонстрирати рекурзивни ЦТЕ.
Примјер:
--прво направим нову табелу
CREATE TABLE dbo.Company
(CompanyID int NOT NULL PRIMARY KEY,
ParentCompanyID int NULL,
CompanyName varchar(25) NOT NULL)
GO
--затим попуним табелу подацима
INSERT dbo.Company (CompanyID, ParentCompanyID, CompanyName)
VALUES(1, NULL, 'Mega-Corp')
INSERT dbo.Company (CompanyID, ParentCompanyID, CompanyName)
VALUES(2, 1, 'Mediamus-Corp')
INSERT dbo.Company (CompanyID, ParentCompanyID, CompanyName)
VALUES(3, 1, 'KindaBigus-Corp')
INSERT dbo.Company (CompanyID, ParentCompanyID, CompanyName)
VALUES(4, 3, 'GettinSmaller-Corp')
INSERT dbo.Company (CompanyID, ParentCompanyID, CompanyName)
VALUES(5, 4, 'Smallest-Corp')
INSERT dbo.Company (CompanyID, ParentCompanyID, CompanyName)
VALUES(6, 5, 'Puny-Corp')
INSERT dbo.Company (CompanyID, ParentCompanyID, CompanyName)
VALUES(7, 5, 'Small2-Corp')
--дефин.превремени скуп са колонама за приказ odnosno CTE
WITH CompanyTree(ParentCompanyID, CompanyID, CompanyName, CompanyLevel)
AS
(
SELECT ParentCompanyID,CompanyID,CompanyName,0 AS CompanyLevel
--ову табелу
FROM dbo.Company
WHERE ParentCompanyID IS NULL
UNION ALL
SELECT c.ParentCompanyID,c.CompanyID,c.CompanyName,p.CompanyLevel + 1
--повезујем са самом собом преко псеоудонима (с), и КомпануЛевел увећавам за 1.
FROM dbo.Company c
INNER JOIN CompanyTree p ON c.ParentCompanyID = p.CompanyID
)
SELECT ParentCompanyID, CompanyID, CompanyName, CompanyLevel
FROM CompanyTree