Вы находитесь на странице: 1из 167

TableofContents

Answers TableofContents Copyright Disclaimer Introduction–SQL-Whyyoushouldlearnit SQLiswidelyused SQLcandomanythings SQLskillsaretransferable LearningSQLissimple MicrosoftSSMS–HowtogetfreeSQLsoftware Thebigpicture Whattodownload Wheretodownloaditfrom

Choosingbetween32-bitand64-bit

Completingthedownload

Installing

Northwind–Howtogetafreedatabasetopracticeon

Thebigpicture

Downloadyourdatabase

Installyourdatabase

ConnecttoyourdatabaseinSMSS

Tables–What’sinadatabase

Introduction

Findingtables

Lookingattables

Whattablesare

Rows

Columns

Relationships

Technicalterms

Thenextstep

SELECT–Howtoquery(getdatafrom)adatabasetable

MakingNewQueries

TheQuery

Theexplanation

Linkedanswers

Howtogetspecificcolumns

Anoteonhowthisbookformatsqueries

SELECT-Howtodocalculationswithinrows

Introduction

Anexample

Keepingthingsorganised

Anoteonunitsofcurrency

Moremath-operators

Constants

SELECTwithoutFROM

Modulus

Brackets

TextStrings

Stringliterals

StringliteralswithAS

Functions

Null

TheIsNullFunction

Otherfunctions

Thenextstep

WHERE-Howtogettherowsyouwant

Matchingvalues

Comments

Case

Clauses

MatchingValuesInexactly

Matchingoncalculations

MatchingtextvaluesinexactlywithLIKE

Colour-coding

Datevaluesandliterals

Datesandtimes

AND/OR/NOT–Howtogettherowsyouwantmoreprecisely

AND-Ranges

AND-Multipleconditions

OR–Beingflexible

Brackets

NOT–Sayingwhatyoudon’twant

DISTINCT-Howtoremoveduplicates

ORDERBY-Howtosortyourrows

TOP-Howtotakeasmallsampleofrows

Bottom

GROUPBY-Howtosummariserowdata

Sum

Aggregatefunctions

OtherAggregateFunctions

Grouping

Groupingbymultiplefields

HAVING-Howtogettherowsyouwant,aftersummarising

Applyingthistoothertables

Multipleaggregatefunctions

Alias-Howtoquerywithlesstyping

ColumnAlias

TableAlias

INNERJOIN-Howtocombinerelatedrecordsfromdifferenttables

Otherwaystojoin

OuterJoins–Howtogetunrelatedrecords

Theproblemwithinnerjoins

Whatitallmeans

LeftOuterJoins

RightOuterJoins

InnerJoinsvs.OuterJoins

FullOuterJoins

Self-Join-Howtojoinatabletoitself,andwhyyouwouldwantto

CrossJoin–gettingallpossiblecombinationsoftablerows

Introducingcrossjoins

Howcrossjoinswork

Usesofcrossjoins

UNION/UNIONALL-Howtocombinerowsfromtwotables

UNIONALL

UNION

INTERSECT–Howtogetrowsthatareonlyinbothtables

EXCEPT–Howtogetrowsthatareonlyinonetable

Sys/Metadata-Howtogetinformationaboutyourdatabase

Learningfromexistingviews

Subqueries-Howtomakeonequeryusearesultfromanother

SubqueriesintheFROMclause

TheINoperator

SubqueriesintheWHEREclause–usingtheINoperator

SubqueriesintheWHEREclause–theALLoperator

SubqueriesintheWHEREclause-the“ANY”operator

Wheretogofromhere

Author’snote

Otherbooksyoumayfinduseful

LearnSQLFast

Aquerywritingcourseyoucanreadonthetrain,basedonsoftware

youcandownloadforfree

Copyright

Copyright©2016byDArmstrong

Disclaimer

Whiletheadviceandinformationinthisbookarebelievedtobetrueandaccurateatthe

dateofpublication,neithertheauthornorthepublishercanacceptanylegalresponsibility

foranyerrorsoromissionsthatmaybemade.Thepublisherandauthormakesno

warranty,expressorimplied,withrespecttothematerialcontainedherein.

Introduction–SQL-Whyyoushouldlearnit

SQLiswidelyused

SQL–StructuredQueryLanguage–isawidelyusedlanguageforworkingwithdata. All organizationshavedata,andtheytypicallystoreatleastsomeofitinadatabase.

SQListhelanguageofdatabases:learningitallowsyoutousethemeffectively.

SQLcandomanythings

SQLallowsyoutoviewdata,analyseit,andperformcalculationswithit. WithSQL,you canchangethedatastoredinadatabase,orchangethewaythedatabaseitselfworks. SQLalsoletsyoumakerulesabouthowdatamaybechangedandwhoby.

ThisbookcoversthemostcommonuseofSQL:gettingdataoutofdatabases. Itshows youhowyoutoview,analyse,andreportondata,whichisthefirststeptobecominga confidentSQLuser,becauseitistheskillthatletsyouseewhatyouareworkingwith.

SQLskillsaretransferable

Therearemanydatabasetechnologies:MicrosoftSQLServer,MySQL,Oracle,Microsoft Access,andsoon. EachhasitsownversionofSQL. However,unlikeprogramming languages,theyareallverysimilar.

SQLskillsinonetechnology,suchMicrosoftSQLServer,canbequicklyandeasily appliedtoanother,e.g.MySQL. LearningSQLonceallowsyoutouseitmanytimes.

LearningSQLissimple

ThisbookisdesignedtomakelearningSQLasstraightforwardaspossible. Itisa concise,step-by-stepcourse,writteninplainEnglish,withafocusonusingwhatyou learn. ItgivesexamplesofSQL(knownas“queries”)whichyoucanrunonyourhome computer,andexplainshowtheywork. Afterthat,thisbookgivespracticeexercises,so thatyoucantryoutwhatyoulearn,beforemovingon. Laterchaptersshowhowto combinethebasicstowritemoreadvancedqueries.

Whenanewtechnicaltermisintroduced,thiscoursewillgiveadefinition,orplain-

Englishequivalent,atthatpoint.

ThesoftwareneededtopracticeSQLwillrunonahomePCorlaptopandisfreely availableonline. Thisbookwillguideyouthroughdownloadingandinstallingthecorrect versionforyourmachine.

Let’sgetstarted.

MicrosoftSSMS–HowtogetfreeSQLsoftware

Thebigpicture

TheexamplesandexercisesinthisbookuseMicrosofttechnologies,althoughas mentionedearlier,onceyouhavelearnedSQLwithonetechnologyitiseasilytransferable toanother. ThebookalsoassumesyourcomputerhasMicrosoftWindowsalready installed.

Youwillneedtwopiecesofsoftware:SQLServeritselfandSQLServerManagement Studio(SMSS). Microsoftprovidesbothonlineforfree,asasinglepackagetodownload andinstall.

SQLServeristhesoftwarethathandlesanySQLqueriesyourun,butitdoesn’tactually displaytheresultsofqueries,orappearonscreenatall. SMSSisthesoftwareyouwill actuallysee:theuser-interface. Thisiswhereyoutypeanyqueriesyouwanttotryout, anditiswhatdisplaystheresults.

Whattodownload

Microsoftoffersseveraldifferent“editions”ofSQLServeronline. SQLServerExpressis thefreeone,andtheonethisbookisbasedon.

WithintheExpressedition,Microsoftalsooffersseveraldifferentdownload“packages”, e.g.advanced,withtools,etc. SQLServerExpresswithAdvancedServicesincludes SMSS,whichyouwillneed,andistheonethisbookisbasedon.

Wheretodownloaditfrom

YoucandownloadafreeversionoftheabovefromMicrosoft’swebsite,byclickingthe

downloadlinkonthewebpagebelow(ifyouGoogle“downloadSQLServer”,thispage

shouldappearnearthetopofyourresults):

Whenyouclickthelink,Microsoft’ssitewillpromptyoutosign-inorregisterforan account. Onceyouhavedonethis,itwillprovideachoiceofSQLServerExpress packagestodownload.

IfyousignupforanewMicrosoftaccountanditdoesn’ttakeyoudirectlytothe downloadoptionsafterwards,gobacktothewebpageabove,clickthedownloadlink again,andsigninwithyournewlyregisteredaccountdetails. Youwillthenbeonthe correctpagetochooseyoudownloadpackage.

Choosingbetween32-bitand64-bit

Youwillnoticethatthenameofthepackageyouneed(SQLServerExpresswith

AdvancedServices)appearstwice,oncefor64-bitsystemsandagainfor32-bitsystems.

Youneedtodownloadtheonewhichmatchesyoursystem. Tocheckwhetheryour systemis64-bitor32-bit,youcanuseanyofthemethodsbelow. Theyarelistedinorder:

fastestfirst. Ifyourcomputerdoesnotsupportonemethod,youcansimplyusethe nextone.

Method1

Goto“search”onyourcomputer. Type“system”. Pressreturn. Thesystemwindowwill appear. Inthesystemwindow,lookdownthelistedinformationtofindthesystemtype. Thiswillstateifthecomputeris64-bitor32-bit. Ifyousee“86”,e.g.“x86based

processor”,thenthismeanstheprocessoris32-bit.

Method2

OpenWindowsExplorer,i.e.openanyfolder,suchas“MyDocuments”,onyour computer. Inthefolderwindowwhichappears,ontheleft,youshouldseeanoption called“MyComputer”,or“ThisPC”,orsomethingverysimilar. Right-clickonthis optionandamenuwillappear. Clickthe“Properties”optiononthismenuandanew windowwillappear. Inthiswindow,lookdownthelistedinformationtofindthesystem type. Thiswillstateifthecomputeris64-bitor32-bit. Ifyousee“86”,e.g.“x86based

processor”,thenthismeanstheprocessoris32-bit.

Method3

Goto“search”onyourcomputer. Type“cmd”andpressreturn. The“commandprompt” (ablackwindow)willappear. Inthecommandprompt,type“systeminfo”,andpress return. Thiswillfillthecommandwindowwithmoreinformationthanfitsonthescreen. Scrollbackuptotopofthecommandwindowandreaddownuntilyoufindamentionof “64-bit”or“x64”,thiswillberecordednextto“systemtype:”orsimilar. Ifyoudon’tsee

that,dothesamechecks,butlookfor“32”or“86”inplaceof“64”,i.e.lookfor“x86”

and“32-bit”. Ifyoufindanyofthese,thenyourcomputeris32-bit.

Completingthedownload

Onceyouhaveselectedapackage,clickonthe“Continue”buttonatthebottomofthe page. Thiswilltakeyoutoapagewhichstartsthedownload. Thedownloadisafolder, notjustonefile.

Ifyourbrowsergivesyoutheoptiontosavethedownload,saveitanywhereyoulike,as longasyouknowwhereitis. Forexample,saveittoyourdesktopforeasyaccesstothe download.

Ifyoudon’tgetthechoiceofwheretosave,itwillalmostcertainlybedownloadedtoyour

computer’sdownloadsfolder,typically“C:\Users\(yourusernamehere)\Downloads”.

Thedownloadmaytakesometime,butitwillcontinuebyitself,soatthispointyoucan

leavetheprocesstofinishitself.

Installing

Openthefolderthatyoujustdownloaded,andyouwillseeafilecalled“SETUP”. Double-clickonthatfiletorunit,anditwilltakeyouthroughtheinstallprocess. This willbetheusualprocess,i.e.aninstallwizard.

Thefirstwindowthatwillopenistitled“SQLServerInstallationCenterOptions”. This willgivetwooptions:“New”and“Upgrade”. Clickon“New”. Thiswillopenasecond

window“SQLServer2014Setup”.

Atthispoint,youcanjustkeepclickingthe“next”buttonuntiltheinstallprocessstarts.

Thewizardwillaskyouthingslikewhetheryouwanttoinstallupdatesautomatically,and

whichtypeofAuthenticationtouseforSQLServer,butnoneofthisislikelytoaffect

youruseofthesoftwareforthepurposesofthiscourse.

Likethedownload,theinstalltakessometime,but,alsolikethedownload,itwill

continuebyitself,soatthispointyoucanleavetheprocessandcomebacktoitlater.

Whentheinstallprocessiscomplete,goto“search”onyourcomputerandtype“SMSS”. TheresultswillshowyouSQLServerManagementStudio. Clicktoopenit. Itmaytake afewminutestoloadupthefirsttimeyoudothis. Whendoesopen,adialogbox(small window)willappear. Clickthe“Connect”buttononthisbox. Yoursoftwareisnowready touse,youjustneedsomedatatouseiton. Thenextchapterwillcoverthat.

Northwind–Howtogetafreedatabasetopracticeon

Thebigpicture

YouhavenowsetupSSMS,whichallowsyoutoenterqueriesandseetheirresults,and SQLserver,whichactuallyrunsthosequeriesondatabases. Whatyouneednowisa databasetorunthosequerieson. Youalsoneedthatdatabasetocontainsometestdatafor thosequeriestofind.

Microsoftprovidesafreedatabaseonline,completewithdata. Thischapterwillshowyou howtogetthatdatabaseandsetitupforusewithSQLServer.

Downloadyourdatabase

TheinstructionsbelowarebasedonusingGoogleChrome,becauseitletsyourunthe installerdirectlyfromthebrowser,whichsimplifiestheprocessalittle. Ifyouarelimited to,orprefertouse,abrowserwhichdoesn’tletyoudothis,thenextsectionhas instructionsonhowtofindtheinstallerfileinyourDownloadsfolderandrunitfrom there.

YoucangodirectlytothepagethatinstructsyouonhowtodownloadNorthwind(or

rather,theNorthwindinstaller),runtheinstallerandthenconnectthedatabasein

SSMS,at:

However,onGoogle,ifyoujuststarttyping“DownloadNorthwind…”itshouldauto-

suggest“…forSQLserver2014”. Ifyousearchforthat,itwill,atthetimeofwriting, giveyouthepageaboveinyoursearchresults.

Thepageabovecontainsasectiontitled“ToinstalltheNorthwindandPubssample databasesforSQLServer”. Inthatsection,steponehasalinktothe“Northwindand PubsSampleDatabasesWebsite”. Thislinktakesyoutoapagewiththeaddressbelow:

Thisisthepageyouactuallydownloadthedatabasefrom. Ignorethefactthatthe

webpagesays“forSQLServer2000”:theNorthwinddatabasewascreatedawhileago,

butnewerversionsofSQLServercanstilluseit. Thewebpagehasabigred“Download” buttononit. Onceyoudownloadthefile,itwillappearasatabinthebottomleftofyour browser(atleast,ifyouareusingChrome). Thefilenameis“SQL2000SampleDb.msi”. Clickingonthisfilewillgiveyoutheoptiontoruntheinstallerstraightaway.

Installyourdatabase

Preferably,runtheinstallerfromyourbrowserasdescribedabove.

Ifforanyreasonyoudon’tget,ordon’tuse,theoptiontoruntheinstallerfromyour browserwhenyoudownloadit,youcanstillproceed. Gotoyour“downloads”folder. Typicallythiswillbeat:“C:\Users\(yourusernamehere)\Downloads”. Double-clickthe installerfiletorunit.

ConnecttoyourdatabaseinSMSS

Thefirstofthetwowebpagesabovedoesincludeinstructionsforgettingsetupwithand

connectingtoyourdatabase,butIthinkthemethodbelowiseasiertofollow,soI

recommendthiswayinstead:

OpenSSMS. Fromthemenubarinthetopleft,clickon“File”,“Open”and“File”. A windowwillappearlettingyoubrowsethroughfolderstofindthefileyouneedtoinstall.

Bydefault,thedatabasefilesareautomaticallycreatedina“SQLServer2000Sample

Databases”folderontheC:Drive.

YoucangettotheC:drivebyclickingthe“computer”,or“mycomputer”,optiononthe leftofyourwindow,thendouble-clickingontheC:driveicon. Fromthere,openthe

“SQLServer2000SampleDatabases”folder.

Fromthatfolder,openthefile“instnwnd.sql”(itmayjustappearas“instnwnd”). Thisisa filecontainingaSQLquerywhichwillsetupthedatabase(createitandfillitwithdata). Openingthefilewilldisplaythetextofthequery,brightlycolor-coded.

Clicktheredexclamationmark“!”(called“execute”)atthetopoftheSSMSwindow. Thiswillrunthequeryandmakethedatabase. Itmaygiveyouacoupleoferrors messageaboutnotbeingabletofindstoredprocedures. Ignorethem.

Ifyounowgotothe“ObjectExplorer”panelontheleftsideofSSMSandright-clickits “Databases”item,thiswillopenamenu. Clickthe“refresh”optionatthebottomofthat menu. Nowclicktheplussigntotheleftof“Databases”tomakeitexpand,showingyou theNorthwinddatabase. Youarereadytobegin!

Tables–What’sinadatabase

Introduction

Beforerunninganyqueries,youneedtoknowwhatdatathereistobequeried. Datais storedintables. Thischapterwillcoverhowtofindthetablesinyourdatabase,andhow toseewhattheycontain.

Findingtables

OpenSQLServerManagementStudioonyourcomputer. Ifyoucan’tfindit,thentyping “sql”or“ssms”inyourcomputer’ssearchfieldwillbringitupforyou.

Ifyoulookintheobjectexplorer,youwillseeacylinder-shapedservericon. Therewill beagreencirclewithawhitetriangle,likea“play”button,onit,anditwillhaveasmall whiteboxtoitsleft,containingaminussign. Clicktheboxtohidetheitemsgrouped undertheicon(databases,security,etc). Thebox’ssignwillalsochangetoa“plus”. Clickitagaintomakethehiddenitemsreappear.

Nowclickonthesignnextto“Databases”tomakeitemsunderthatvisible. Repeatthese stepson“Northwind”andthen“Tables”. Thiswillshowyoualistofallthetablesinthe database.

Lookingattables

Right-clickonthe“dbo.Products”tableandamenuwillappear. Onthemenu,clickthe optionfor“SelectTop1000Rows”. ThiswillopenatabinthemainpartofyourSSMS window,andthebottomhalfofthetabwilldisplaythecontentsofthetable. Thistable doesn’thaveathousandrows,sothetabjustshowsyoutherowsitdoeshave. Ifthetable hadmorethanathousandrows,youwouldseethefirstthousand.

Youwillseethatthetableisalistofproducts,oneproductperrow. Youwillseethateach columnholdsaspecificpieceofinformationabouteachproduct:itsIDnumber,name, price,etc.

Use“SelectTop1000Rows”tolookattheCategoriestable(“dbo.Categories”). Youwill seealistofproductcategories,oneperrow,withspecificinformationaboutthose categoriesineachcolumn.

Youcanhavemultipleopentabsatatime,however,oncetheyfillthewindow,SMSSwill starttomovetabsintoadrop-downmenu,andtheybecomelessconvenienttoworkwith. Havingtwoorthreetabsopenatoncecanbeusefulthough. Youcanuseoneortwotabs asareference,toseewhattablescontain,andanothertowriteaqueryonthosetables.

Butfirst,nowthatyouhavesomeexamplesonscreen,we’llcoverwhatdatabasetables

actuallyare.

Whattablesare

Tablesarewheredatabasesstoredata. InNorthwind,forexample,wehavetablesof employeesregions,products,andsoon. Eachofthesetablesstoresdataaboutaparticular typeofperson,placeorthing. Thetechnicaltermforthisis“entity”. Employeesareone typeofentity,regionsareanother,andproductsathird. Entitiescanalsobemoreabstract, non-physicalthings,suchasproductcategories. Theycanbetypesofeventsoractions, suchascustomerorders. Alloftheabovewouldhavedifferentdatarecordedaboutthem, soeachofthemwouldneedtheirowntable.

Rows

Eachtablerow,or“record”,holdsdataaboutoneexample,or“instance”,ofanentity. So anemployeewouldgetonerowintheEmployeestable. Eachnewemployeewouldbeon anewrow. Thenumberofrowsinatablecanbeanythingfromzeroupwards,andcan changeovertimeasthedatabaseusersaddordeleterecords.

Columns

Acolumn,or“field”,holdsspecificdataaboutoneaspectoftheentitiesinitstable. So onecolumnmightholdthefirstnamesoftheemployees,thenextmightholdthelast names. Thenumberofcolumnsisfixed,anddoesn’tchangeunlessthedesignofthe databaseischanged,e.g.byadeveloper.

Relationships

TherecordsintheNorthwindtablesarerelated. Forexample,acustomermayhave severalorders,soonerowintheCustomerstablewouldbeassociatedwithseveralrowsin theOrderstable. Toseeanotherexample,returntotheProductstable“dbo.Products”. ThefirstrecordinthetableisforChai,anditsCategoryIDis1. Ifyoulookinthe Categoriestable,youwillseethatthisCategoryIDnumberisforbeverages. So,ifyou didn’talready,younowknowthatChaiisabeverage. Thetablesarerelatedbytheir CategoryIDfields. Laterinthebook,we’llseehowSQLcanusethisfeaturetogather relateddatafromseveraltablesatonce.

Technicalterms

Therearequiteafewtechnicaltermstodowithdataanddatabases. Wheneverthisbook introducesanewterm,itwillusuallybeinquotes,likethis:

Columnsindatabasetablesarealsoknownas“fields”.

However,whenthereisaplainEnglishequivalent,thetermmaysimplybegivenafterit,

inbrackets,likethis:

Columns(fields)storespecifictypesofdata,e.g.onefieldmaystoreproductnamesand

anothermaystoretheirprices.

Thenextstep

Thenextchapterwillshowyouhowtogetdatafromatable. Afterthat,you’llseehowto specifywhichfieldsyouwanttoviewforeachrecord. Onceyouknowhowtogetthe datainthose,we’llmoveontodoingthingswithit.

SELECT–Howtoquery(getdatafrom)adatabasetable

MakingNewQueries

Inthetopleftofthewindow,underthemenuoptionsfor“file”,“edit”,“view”,andthe others,isthe“NewQuery”button. Clickonthatbutton. Thiswillmakeablanktab appear. Also,thewhitedrop-downboxbelowthe“NewQuery”buttonshouldnowsay “Northwind”. Ifitdoesn’t,e.g.ifitsays“master”,clickonitandchoosetheNorthwind optionfromthelist. Youmayhavetodothiswithothernewqueriesinfuture,asitcan defaultbackto“master”. Ifyourunaqueryandgetanerrormessagesayingthatthe thingsyouarequeryingcan’tbefoundordon’texist,thisissomethingworthchecking.

Now,intheblanktabyoujustopened,typethetextbelowforyourfirstSQLquery.

TheQuery

Type:

SELECT*

FROMPzyxroducts

Youdon’tneedtotypethe“dbo.”partofthetablename,asMicrosoft’ssoftwaredefaults tothatanyway. Also,youdon’tneedtousecapitalsinyourqueryifyoudon’twantto (andit’sfastertotypeifyoudon’t). Thisbookusescapitalspurelytomakeclearwhich wordsareSQLkeywords,e.g.SELECT,andwhicharenot,e.g.Products. Finally,it doesn’tmakeanydifferencehowmanylinesyouspreadyourqueryacross. Ifyoutype thequeryaboveallononeline,itworksexactlythesame.

Clickthe“Execute”buttononthetoolbaraboveyourquerytab,orjustpresstheF5key

onyourkeyboard. Thiswillrunyourquery. Youwillseetheresultsofyourqueryappear inthebottomhalfofthetab.

Theexplanation

Thisquerygetsalltherowsandcolumns,andthereforeallthedata,fromtheProducts table. The“SELECT”keywordtellsthesoftwarewhichcolumnstoretrieve. The“*” symbol(asterisk)tellsittoget(return)allcolumns.

The“FROM”keywordsayswhichtabletotakedatafrom. FollowedbytheProducts tablename,itsaystotakedatafromProducts. Bydefault,SQLreturnsallrowsfromthe tablesitqueries. Inlaterchapters,we’llexplorewaystoreturnonlytherowsyouneed.

Tosummarise,theabovequerysays“takethedatafromallcolumnsoftheProducts

table”.

Ifyoujustwanttoseethecontentsofatable,thistypeofqueryisuseful. Infact,thistype ofqueryisespeciallyusefultoSQLusers,i.e.you. Youcanuseittoquicklyseethe contentsofatablebeforetakingthetimetowritemoreadvancedqueries. Onceyouhave seenthestructureandcontentsofatable,itiseasiertoqueryitinmorespecificways,as wewilldolater.

Exercise–1.1

(answer)

GetalldatafromtheCategoriestable. WriteandrunthequerytodothisinSSMS.

Linkedanswers

Whenyouhavedonethisexercise,youcanclickonandfollowthe“(answer-1.1)”linkto

compareyourquerytotheoneintheanswer. Alltheexerciseshavehyperlinkedanswers, whichyoucanrefertoifyougetstuckorwanttocheckthatyouransweriscorrect.

Whenyoucheckananswer,youcanuseyoure-reader’sbackbuttontoreturntothemain partofthiscourse. However,justincaseyoudon’thaveabackbutton,orit’sbroken,or youcan’tuseitforsomereason,eachansweralsoincludesalinkbacktoits correspondingexercise.

Howtogetspecificcolumns

Nowreplacetheasteriskinyourquerywiththenamesoftwocolumns,i.e.

SELECTCategoryName,Description

FROMCategories

Runthequery(Execute/F5)andseehowitonlyshowstwocolumns. Notethat,with morethanonecolumninthequery,youhavetoseparatecolumnnameswithcommas.

Exercise–1.2

(answer)

Foreachproduct,displayitsname,priceandthenumberofunitsinstock.

Anoteonhowthisbookformatsqueries

Thisbookputseachpartofaqueryonanewline,tomakethemeasiertounderstand. It alsohelpsqueriesfitneatlyontothescreenofyoure-reader. However,asscreensizes andquerylinelengthsvary,youre-readermaysometimessplitonelinefromthebook acrossseverallinesonthescreen. Thesesplitlineswillappearclosertogether,asbelow:

ThisisoneverylonglineoftextwhichisnotSQLbutdoesshowhowclosetogether

linesoftextappeariftheyareseparatedautomaticallybyane-readertomakesurethey

fitonascreen.

Ontheotherhand,textwhichisputontwolinesappearswithabiggergapinthemiddle,

likethis:

Line1

Line2

Thenextchapterhassomelonger“SELECT”statements,soyoumaynoticethiseffect there. Thisnoteisincludednowtopreventanyconfusionaboutthelayoutofsuchqueries laterinthebook. Ultimatelyhowever,SSMStreatsline-breakslikespaces,whichmeans thatwhenyoutypeinyourqueries,youcanformatthemacrosshowevermanylines youlike.

SELECT-Howtodocalculationswithinrows

Introduction

ThischaptercoverscommontasksinSQL,suchasperformingbasicmathoperationsand handlingfieldswithoutvaluesin. Itdemonstratesthesewith“SELECT”,asthisprovides awaytodisplaytheresultson-screen. However,apartfromtheuseof“AS”torename columnsinqueryresults,allofthethingsinthischaptercanbeusedinotherways. You willseesomeexamplesofthiswithotherSQLkeywordsinlaterchapters.

Anexample

Enterthequerybelow:

SELECTProductName,UnitPrice,UnitsInStock,UnitPrice*UnitsInStock

FROMProducts

Whenyourunthis,youwillsee,inthelastcolumn,thetotalvalueofthestockthe companyholdsforeachproducttype. Puttingthe“*”characterbetweenthetwofields (“UnitPrice”and“UnitsInStock”)tellsthecomputertomultiply,oneachrow,thenumbers theycontain.

Keepingthingsorganised

Youwillnoticethefourthcolumnhasnousefultitle. Tofixthat,add“ASStockValue”,to thequery,asshownbelow.

SELECTProductName,UnitPrice,UnitsInStock,UnitPrice*UnitsInStockAS

StockValue

FROMProducts

Runthequerynow,andyouwillseethatthetitle“StockValue”hasappeared. Youcanuse the“AS”keywordtogiveatitletoanycolumnthatappearsinyourqueryresult.

Exercise–2.1

(answer)

Changethequeryabovesothat“ProductName”appearsas“Product”.

Anoteonunitsofcurrency

Onceyoubecomefamiliarwiththedatabase,itwillbecomeclearthatitrepresentsaUS

companythattradesinternationally,whichalsohasaUKbranch.

Databasefieldscontainingcurrencyvalues,suchas“UnitPrice”,don’tincludeunits. They

say“10.00”ratherthan“$10.00”,or“£10.00”,orsimilar.

Thecurrencytypeisn’timportantforthiscourse. Currencyvaluesarereferredtointhe

samewayasothernumbers,e.g.“thisquerylistsproductsworthmorethan3.50perunit”,

andyoucanthinkofthemaswhichevertypeofcurrencyyouprefer.

Moremath-operators

Todoothercalculations,simplyswapthe“*”for“/”todivide,“-”tosubtract,and“+”to add. Thesecharactersarecalledoperators,e.g.“/”isthedivisionoperatorand“10/2”is adivisionoperation.

Exercise–2.2

(answer)

Getthenameandtotalvalueofitemsonorderforeachproduct.

Youcanspecifynamesforyourresultscolumnsifyoulike,butfromhereontheanswers

won’tincluderenamingunlesstheexercisespecificallyasksforit.

Exercise–2.3

(answer)

Assumealltheproductsonorderhavejustarrived. Showhowmanyofeachproductyou nowhave.

Constants

Sometimes,youmayneedtouseafixedvalue,or“constant”,inyourquerycalculations. SupposeNorthwind’squalitycontroldepartmenthadsignedoutthreeunitsofeach productfortestingandnowwantstoreturnthem. Youwanttoseehowmanyunitsyou willhavewhentheydo. SQLcanshowyouthiseasily.

SELECTProductName,UnitsInStock+3

FROMProducts

Youcanusedecimalsthesameway. Forexample,tocalculatea20%salestaxonunit price,seebelow:

SELECTProductName,UnitPrice*0.2

FROMProducts

Exercise–2.4

(answer)

Findawaytoshowthevalueofthe20%salestaxoneachproduct,usingdivision,instead

ofbymultiplying.

SELECTwithoutFROM

Beforegoinganyfurther,itisworthnotingthatyoucanalsorunaquerywithoutreferring toanytableatall. Youcanuse“SELECT”without“FROM”. Forexample,tryrunning:

SELECT8

Youwillseeasingle“8”asaresult.

Thefactthat“SELECT”worksonitsownisusefultoknow,especiallywhenstartingout withSQL. ItprovidesasimplewaytotryoutcalculationsinSQL. Forexample,to

divide10by2,use:

SELECT10/2

Exercise–2.5

(answer)

Findtheanswerto“seventimeseight”.

Modulus

Thereisanothermathoperator:“%”. Thisiscalledthemodulusoperator. Itworksout theremainderofadivision. Forexample,14%5is4,because5goesinto14twice,with

4leftover;whereas21%7is0,because7goesinto21threetimesexactly,sonothingis

leftover. Trythisoutasbelow.

SELECT14%5

And:

SELECT21%7

Unliketheothermathoperators,youmayneverneedtousethemodulusoperator. Ifyou dowanttopractiseworkingwithit,trythenextexercise.

Exercise–2.6

(answer)

LookattheProductstableagain. Ifyoustoreallunits(currentlyinstock)foreach productingroupsoftwelve,showhowmanyunitsofeachproductwillbeleftover.

Brackets

Todomorecomplexcalculations,youneedbrackets. Toseewhy,runtheexamples below.

SELECT(2+2)*5

And:

SELECT2+(2*5)

Theresultswillbedifferent:20and12.

Inthecalculationsabove,thebracketschangetheorderoftheoperations. Thischanges theresults. Calculationsinsidebracketshappenfirst,sothefirstexampleis2+2=4

followedby4*5=20,whereasthesecondexampleis2*5=10followedby2+10

=12.

Exercise–2.7

(answer)

Getthecombined(instockandonorder)totalvalueofeachproduct,e.g.ifthereare10

goodsinstock,and10onorder,withaunitpriceof5,thenyourqueryshouldreturnthe

valueas100.

TextStrings

The“+”signhasanotheruse. Ifyouhavecolumnsoftext,ratherthannumbers,youuse “+”tocombinethem. Forexample,intheCustomerstable,youhavefieldsforaddress andcity. Runthequery.

SELECTAddress+City

FROMCustomers

Itwillshowbothvaluesforeachrow,butinonecolumn.

Stringliterals

Thequeryabovewillalsodisplaythetext(string)valuesineachrowwithoutany formattingcharacters,suchasspacesorcommas,betweenthem. Wecanfixthiswitha stringliteral,i.e.byrunning:

SELECTAddress+‘,‘+City

FROMCustomers

ThesinglequotesaroundthecommaandspacetellSQLtotreatthemastext,ratherthan

asafieldnameorSQLkeyword.

Tobetechnical,whenyoucombinetwotextstringsinthisway(joiningonetotheendof theother),you“concatenate”them. The“+”symbolistheconcatenationoperatorinSQL.

Exercise–2.8

(answer)

Changethequerytoincludethecustomercontactnameatthebeginningoftheresult column. Followthesameformat.

StringliteralswithAS

Runthequerybelow.

SELECT‘somevalue’ASwhatever

Thisqueryworks.

Nowrun:

SELECT‘somevalue’ASsometitle

Thisquerydoesn’twork. Thereasonisthatthereisaspaceinthetitlename. The computerreadsthespaceafter“some”asmarkingtheendofthecolumntitleandthen doesn’tknowwhattodowiththeseeminglyrandomword“title”thatappearsattheendof thequery.

Ifyouwanttohaveaspaceinyourresultscolumntitle,youneedtoworkaroundthis.

Thewaytodothatistogivethetitleasastringliteral,e.g.

SELECT‘somevalue’AS‘sometitle’

Nowitworks.

Ifyouintendtore-usequeryresults,e.g.aspartofasubquery(wecoverthislater),it’s bettertoavoidcreatingtitleswithspacesin. SQLcanonlyre-usesuchnamesiftheyare wrappedinsquarebrackets,e.g.“[sometitle]”,andthismakesthequerylessreadable. A fairlyreadablealternativetospacesinmulti-wordtitlesistocapitalisethefirstletterof eachword,e.g.“SomeTitle”.

Exercise–2.9

(answer)

Addthetitle“NameandAddress”totheresultcolumnofthequeryinthelastexercise.

Functions

Afunctionissomethingwhichreturnsavalue. Toseeanexample,run:

SELECTGetDate()

Thiswillreturnthecurrentdateandtime. Runitagainandthevalueitreturnswillchange toreflectthecurrenttime.

Inthiscourse,allfunctionnameswillbewrittenwithacapitalletteratthebeginningof eachword. Thisistomakethemmorereadable,andhelpidentifythemasfunctions.

The“GetDate”functionisperhapsalittleunusualinthatyoudon’tgiveitaninputvalue. Generally,functionsdotakeinputvalues(arguments)andreturnoutputvaluesbasedon them. Onecommonly-usedfunctionthatdoesthisiscalled“IsNull”. Beforeusingit, however,weneedtointroducetheconceptof“null”.

Null

Anullvalueisthecomputerequivalentofablankspaceonapaperform. It’slikeafield thathasn’tbeenfilledinyet,avaluewhichdoesn’texist. Run:

SELECT*

FROMOrders

Usethescrollbarinthebottomoftheresultswindowtolookthroughthecolumnsuntil youreachthe“ShipRegion”field. Someofthevaluesinthiscolumnarenull. Itappears thatsomecountrieswhichNorthwindshipsgoodstodon’tusearegionaspartofthe destinationaddress. Inthiscase,itiscorrectforthecolumntohaveanullvalue.

Northwinddoesn’thavemanynullvalues,butNorthwindisamodeldatabase. Thatis,it hasbeensimplified. Inreal-worlddatabases,nullvaluestendtobemuchmorecommon.

Theproblemwithnullvaluesisthattheyarenotvalues. Forexample,whatis2+null? Findoutwiththequerybelow:

SELECT2+null

Theanswerisnull. Twomorethananunknownvalueisstillanunknownvalue. Thisis correctbutunhelpful. Therearemanycaseswherewewillwanttoreplacenullwith somethingmoreusefulinourresults. Forexample,ifwewantedtocombineour “ShipRegion”columnwithanotherstring,wewouldn’twanttoincludethenull. Inthese cases,weusetheIsNullfunction.

TheIsNullFunction

Typethequerybelow.

SELECTOrderID,ShipCity,IsNull(ShipRegion,”)ASShipRegion,ShipCountry

FROMOrders

Thefunctiontakestwoarguments,whichhavetobeenteredbetweenitsbrackets,witha commabetweenthem. Thefirstisthenameofthefield,inthiscase“ShipRegion”. The functionwillcheckifthisvalueisnull. Thesecondargumentcanbeanyvalue,inthis caseweusedtwosinglequotes,i.e.astringliteralwithnocontents,knownasanempty, orzerolength,string. Runthequeryandyouwillseethatthe“ShipRegion”columnnow showsblankspaceswhereitusedtosay“null”. Foreachrow,thefunctionchecksifthe firstargument’svalueisnull. Ifthevalueisnotnull,thefunctionreturnsthatvalue. Ifthe valueisnull,thefunctionreturnsthesecondargument’svalueinstead.

Toseeareallysimpleexample,run:

SELECTIsNull(null,0)

And:

SELECTIsNull(1,0)

Inthefirstquerythefunctionisgivenanullvalue,andoutputsthespecifiedalternative:

zero. Inthesecondquery,thefunctionisgivenanon-nullvalue“1”,andsooutputsthat value.

Exercise–2.10

(answer)

ModifythequeryoftheOrderstableabovesothatitreturnstwocolumns:OrderIDand theotherthreevaluesformattedaspartofanaddress,i.e.withcommasandspaces between. Nametheaddresscolumn“OrderAddress”.

Exercise–2.11

(answer)

IfyourunthequeryintheanswertoExercise2.10above,youmaynoticethatwhenthere

isnoregionforarow,theresultshowstwo“commaplusspace”separatorstogether. This isbecausethequeryselectsbothstringconstantseverytime. Itispossibletomakethe queryputthisformattingonlybetweennon-blankfields. Youcandothisbyre-arranging howitselectstext. Seeifyoucanworkouthowtodothis.

Exercise–2.12

(answer)

ModifythequeryinExercise2.11abovesothatitdoesn’tusetheIsNullfunctionaround

ShipRegion. Whatdoesthequeryreturnnow?

ThisshouldshowtheusefulnessoftheIsNullfunction.

Otherfunctions

Therearemanyotherfunctionsforhandlingallkindsofdata. Therearefunctionsfor gettingpartsoftextstrings,orconvertingthembetweenupperandlowercase. Thereare functionsforroundingnumbersupanddownandtospecifiednumbersofdecimalplaces. Theremanylesswell-knownfunctionstoo. Eventhen,allofthefunctionsmentionedso farinthisbookareonlytheonesusedtodocalculationswithineachrow,the“in-line”,or “scalar”functions. Thereareothertypesoffunctionswhichwillbecoveredlater. Itis usefultoknowhowtousefunctions,anddocalculations,particularlytheoneswehave coveredhere. However,SQLisn’taboutprocessingonelistofvaluesintoanotherlistof values. Itcandothat,butasthiscoursewillshow,SQLcando,andisdesignedtodo, alotmore.

Thenextstep

AmajorstrengthofSQLisinspecifyingwhichdatatoget. Thischapterhascovered selectingcolumnsfromtables,andprocessingtheirvalues. Thenextwillcoverselecting rows. DoyouneedalistofonlyyourcustomersbasedinGermany? Youneedyourquery toreturnonlycertainrows. Doyouwanttoseewhichordersshippedyesterday? That’sa setofrowstoo. Readontoseehowtogetthem.

WHERE-Howtogettherowsyouwant

Matchingvalues

DidIhearthatyouneedtherecordsofonlyyourcustomersbasedinGermany? Youdo? Thenrunthisquery:

SELECT*

FROMCustomers

WHERECountry=‘Germany’

Ifyouusethescrollbaratthebottomofyourqueryresults,youshouldbeabletoconfirm

thatalltherowsselectedhavetheword“Germany”inthecountrycolumn.

The“WHERE”keywordisfollowedbyacondition,e.g.“Country=‘Germany’”. The querychecksthecondition,e.g.comparesthecountryfieldtothetextstring“Germany” foreachrow. Iftheyareequal,thecomparisonreturnstrue,i.e.confirmsthatthe conditionismet,andtherowisincludedinthequeryresult.Iftheyarenotequal,the comparisonreturnsfalse,andtherowisfilteredoutoftheresults.

Exercise–3.1

(answer)

GetalistofcustomersinBerlin.

Exercise–3.2

(answer)

GetonlythecontactnamesandphonenumbersofcustomersinBerlin.

Comments

Asthecourseprogressestomorecomplexqueries,andtheexercisesbecomemore challenging,youmayfindthatsomeofyourqueriesdon’treturntheresultyouexpected, ormaybeevenreturnanerrormessageinstead. Ifthequeryisverylongandcomplex, youmayhavetroublefindingoutwheretheproblemis.

Whenthishappens,thereisasimplewaytomove,systematically,towardswritingthe queryyouneed. Itisknownas“commentingout”. Hereisa(ratheroversimplified) exampletoshowhowitworks. Supposeyouwantedtocorrectthequerybelow:

SELECT*

FROMCustomers

WHERECountry=‘Germamy’

Ifyourunthisquery,yougetjustthecolumnheaders,butnoresults.

Nowtypetwodashes“—”infrontofthelastlineandrunitagain:

SELECT*

FROMCustomers

—WHERECountry=‘Germamy’

The“—”atthebeginningofthelastlinemarksitasacomment. Commentsareawayfor peopledesigningqueriestoaddnotestotheminplainEnglish. Thesenotesareignored bythecomputerwhenitrunsthequery,sothelastlineistakenasacommentandignored, buttherestofthequeryruns,andalltherowsfromtheCustomerstablearereturned.

Changingthequerylikethisallowsyoutotestpartsofaquerytoseeiftheyworkas expected. Itismuchquickerthandeletinglinesandre-typingthemlater.

Inthiscase,wecanseethatthe“SELECT”and“FROM”linesareworkingcorrectly,so theproblemmustbewiththe“WHERE”line. Thenwecanlookatthatonelineandfind issue.

Whilsttheprobleminthislinewasobvious,theproblemcouldbemoresubtle. Theline couldhaveread:

WHERECountry=‘Germany’

Thespacebeforethecountrynamecouldbehardtospot,especiallyinalongquery.

Queriescanhaveanynumberoflines. Howmanylinesaquerycontainscanvary dramaticallydependingonthedatabase.Severalhundredlinesisnotanunrealisticamount toexpect,especiallyifthequeryusesunions(coveredlater). Insuchcases,youcanbreak downthequeryintoindividualpartstobetested,untilyoufindthepartthatneedstobe changed.

Case

WhenSQLServermatchestext,itignoresthecaseoftheletters. Ifyouput“berlin”in yourWHEREclauseinsteadof“Berlin”,youwillstillgetthesameresults.

Clauses

SQLhascertainkeywordsitusesagainandagain:SELECT,FROM,WHERE,andother whicharecoveredasthecoursecontinues. Thesekeywords,togetherwiththetextthat followsthem,areknownasclauses. Thatis,youhaveaSELECTclause,aFROMclause, andsoon.

Let’susetheseclausestoqueryadifferenttable.

Exercise–3.3

(answer)

GetalistofthecitiesinJapanwhereyouhavesuppliers.

Exercise–3.4

(answer)

TryjustoncetogetalistofthecitiesinIndiawhereyouhavesuppliers,thencheckthe

answersection.

MatchingValuesInexactly

Notallvalueswillbeanexactmatch. Often,youmaywanttoseeallrowswherethe valuesarewithinacertainrange. Supposeyouwanttoseealistofproductswithlessthan tenunitsinstock,soyoucanre-order. Runthisquery:

SELECTProductName,UnitsInStock

FROMProducts

WHEREUnitsInStock<10

Therearetwothingstonoteaboutthisquery. Oneisthatwereplaced“=”witha“<”,the less-thansign,tocomparethevaluesdifferently. Theotheristhatthe“10”,beinga number,isnotenclosedinsingle-quotes.

Thereareothercomparisonoperatorswecoulduse,asfollows:

Greaterthan:>

Greaterthanorequalto:>=

Lessthanorequalto:<=

Notequalto:<>

Exercise–3.5

(answer)

Changethequeryabovetoshowproductswithtenormoreunitsinstock.

Exercise–3.6

(answer)

Nowshowthenamesandpricesofallproductswithapriceabove21.35.

Matchingoncalculations

Whencalculationswereintroducedearlier,theywereusedwith“SELECT”,butas mentioned,theydon’thavetobe. Youcan,forexample,usecalculatedvalueswith “WHERE”,forexample:

SELECT*

FROMProducts

WHEREUnitsInStock+UnitsOnOrder>100

Thisreturnsthetwelveproductswheretheresultofthesumaboveisgreaterthanone-

hundred.

Exercise–3.7

(answer)

Showalistofproductswithcurrentstockworthlessthanone-hundred.

MatchingtextvaluesinexactlywithLIKE

Youmayalsoneedaninexactmatchforatextfield. Forexample,ifyouwanttofindthe typesofcoffeeyousellyoucouldrun:

SELECT*

FROMProducts

WHEREProductNameLIKE‘%coffee%’

ThisgivesyouanyrowswheretheProductNamefieldcontainstheword“coffee”,evenif thereisothertextbeforeorafterit. The“%”symbol,whenusedafter“LIKE”,inatext string,willmatchanycombinationofletters(includingnolettersatall). Itisknownasa “wildcard”. Youneedtouseitbeforeandafterthewordyouwanttomatch,astheremay betextineitherofthoseplaces.

Exercise–3.8

(answer)

Useaquerytoshowalistofallproductnamesbeginningwith“P”.

Colour-coding

Asstatedbefore,itdoesn’tmattertothecomputerwhetherSQListypedincapitalsornot:

itworkseitherway. Inthisbook,theSQLkeywords,like“WHERE”,whichform clauses,arewrittenincapitals,tohelpmakeclearwhattheyare. Ifyoulookatyour queriesinSSMS,youmaynoticethatthesewordsarecolour-codedblue.

However,theword“LIKE”isgrey,notblue,indicatingthatitisdifferent. Ifyoulookat the“=”inyourquery,youwillseethatthissymbolisgreytoo,indicatingthatitis categorisedtogetherwith“LIKE”. Thismeansthat“LIKE”isanoperator. Itisa comparisonoperator,alongwith“=”,“<>”,“>”,etc. Inthisbook,operatorsarealso shownincapitals,buttheircolourinSSMSidentifiesthemaspartofanotherclause, ratherthanthestartofanewone.

Datevaluesandliterals

Beforedoinganymorecomparisons,thereisanothertypeofdata,or“datatype”,thatwe needtocover. Wehavecoveredtextstringsandnumbers. Wewillnowcoverdates. DatesinSQLareformattedlikestringsandtreatedlikenumbers(althoughSQLuses specialfunctionstodocalculationswiththem,ratherthantheusualmathoperators). For

example,ifyouwanttoseealloftheordersfromFebruary1998andbefore(yes,the

Northwindsampledatabasewasmadealongtimeago),youcanwriteaqueryasfollows:

SELECT*

FROMOrders

WHEREOrderDate<‘1998-03-01’

Notethatalthoughyouenclosethedateinquotesasyouwouldwithtext,itisstillusedas anumberforthecomparison. SQLsimplytranslatesthe“<”signto“before”ratherthan “less-than”inthisquery.

Also,althoughtheformatisYear-Month-Day,orYYYY-MM-DD,itispossiblethatyou

willcomeacrossadatabasewherethedatesarestoredinadifferentformat,e.g.YYYY-

DD-MM. Ifyouareusing,saySQLserver,youcancheckthisbylookinginsidethe tables. However,insomesystems,suchasMicrosoftAccess,columnsintablescan, confusingly,besettodisplaydatesindifferentformatstohowtheyarestored. Thiscan leadtosomeeasilyoverlookedtypesoferror.

Exercise–3.9

(answer)

Listtherecordsofallemployeeshiredfrom1993onwards.

Datesandtimes

InNorthwind,thedatabasecolumnssuchasorderdatestoreninezeros,i.e. “00:00:00.000”,aftertheendofthedates. Thesearetimevalues. Theyarestoredinthe formatHours-Minutes-Seconds-Milliseconds. Inthiscase,timesareclearlynotbeing recorded,andthedatabaseisstoringthetimepartofeachdateaszero. Effectively,each date-timevaluerecordedisforthebeginningofthedatespecified,i.e.midnight.

Somedatabasefieldsaresetupwithdatesonly,butmanyrecordtimes. Thisaffectsthe waytheyshouldbequeried,asdescribedbelow.

Timevaluesprovideagoodreasonnottouse“=”withdates. Supposeyouwriteaquery’s “WHERE”clauseas:

WHERESomeDateField=‘2016-01-01’

Ifyourfieldcontainsatimevaluetoo,youwillonlyseerecordswherethetimevalueis exactlymidnight. Youmayhaveathousandrecordsthatday,between9AMand5PM,but youwillseenoneoftheminyourqueryresult.

Whatyouneedisawaytoseeresultsacrossthewholerangeoftimeswithintheday. The nextchapterwillintroducesomeSQLkeywordswhichwillallowyoutodojustthat,and morebesides.

AND/OR/NOT–Howtogettherowsyouwantmore

precisely

AND-Ranges

Sofar,allofthequerieshaveselectedrowsaccordingtowhethertheymetonecondition. Thischapterwillshowyouhowtocombinemultipleconditionstofocusyourqueryonthe rowsyouneed. Indoingso,itwillalsoprovideawaytodealwithdates.

Inthelastchapter,inbecameclearthatwecouldn’treliablyselectdatesusingthe“=” operator. Anydatewithanon-zerotime-valuewillnevermatchadateintheformat:

“YYYY-MM-DD”,asitsvaluewillalwaysbebetweentwosuchdates.

Whatweneed,then,isa“BETWEEN”operator.

SELECT*

FROMOrders

WHEREOrderDateBETWEEN‘1997-01-01’AND‘1997-01-02’

Runthisquery. Yougetalistofordersin-betweenthetwodates,butyoualsogetarecord withanorderonthequery’sseconddate. Thisisbecausethe“BETWEEN”operatoris “inclusive”ofthetwodatevalues.

However,insomeversionsofSQL,“BETWEEN”maynotincludethedates. Itmaybe “exclusive”andtherefore,inthiscase,withourtime-freedatefields,itmayreturnno recordsatall.

Ideally,wewantaquerythatwillworkasweexpect,inanyversionofSQL,whetheror

notthedate-timefieldcontainstimevalues. Inthiscase,wewantaresultthatincludesall

therecordswegotinthelastquery,exceptthosewithanorderdateofexactly‘1997-01-

02’. Trythequerybelow:

SELECT*

FROMOrders

WHEREOrderDate>=‘1997-01-01’

ANDOrderDate<‘1997-01-02’

Thisgivesusonlytherecordsonoraftermidnightofthefirstday,andbefore,butnoton, midnightofthenext. Itisalsoveryclear,fromreadingthequery,howitworks.

Thisqueryusesthe“AND”operatortoextendthe“WHERE”clause(theSSMScolour-

codingexplainedearliershouldmakethiseasiertosee). Eachdatecomparisonforeach rownowreturnsavalueoftrueorfalse,thistimetothe“AND”,whichonlyreturnstrue

tothe“WHERE”clauseasawholeifitgetstwotrueinputs,i.e.condition1istrueAND

condition2istrue.

Operatorslike“AND”,whichprocessvaluesoftrue/false,areknownaslogical,or

Boolean,operators,asopposedto,forexample,themath,orarithmeticoperators,like“-”

and“/”.

Theuseof“AND”hereallowsyoutogetvaluesinadaterange. However,itsuseisn’t limitedtoworkingwithdates. Itcanbeusedwithanycombinationofconditions.

Exercise–4.1

(answer)

Getalistofproductswithatleasttenbutlessthantwentyunitsinstock. Showthestock levelsinyourresults.

Filteringresultsonarangeisjustoneusefor“AND”. Youcanalsouseittofilterresults onseparatefields,asinthenextexercises.

AND-Multipleconditions

Exercise–4.2

(answer)

GettherecordsforordersshippedtoBrazilfrom1997onwards.

Exercise–4.3

(answer)

GettheordersshippedtoBrazilin1997(youcanuse“AND”asmanytimesasyoulike,

justkeepaddingtheoperatorfollowedbyitsconditiontotheendofyour“WHERE”

clause).

OR–Beingflexible

Whatifyouwanttogetresultsthatmeeteitheroftwoconditions? Forexample,youmay wantalistofordersshippedtotheUSandCanada. Youcan’tusethe“AND”operatorfor this:itwillonlyreturnordersthatwenttobothcountries,i.e.noorders. Youneedan “OR”operator.

SELECT*

FROMOrders

WHEREShipCountry=‘USA’

ORShipCountry=‘Canada’

The“OR”takestheresultsofthetwocomparisonsand,ifeitheroneistrue,returnsa resultoftrue. Therowisthenincludedintheresults.

Let’sapplythistoanothertable.

Exercise–4.4

(answer)

TheUKsalesteamarevisitingtheSeattleoffice:listtherecordsofanyemployeesyou

wouldnowexpecttobeinSeattle.

Brackets

Ifyouthinkbacktothechapteron“SELECT”andmath,whenbracketswereintroduced,

youmayrememberthatoperationsinsidebracketshappenbeforethoseoutsideofbrackets

Trythefollowingquery:

SELECT*

FROMCustomers

WHEREContactTitle=‘Owner’

AND(Country=‘USA’

ORCountry=‘Mexico’)

Thisqueryreturnsalistofcustomerswhereyourcontactisthebusinessownerandwhich arebasedinMexicoortheUS. Thequerycomparesthecountryfieldfirst,andifeitherof thecomparisonsistrue,italsochecksthe“ContactTitle”. Ifthisis“Owner”thenit includestherowintheresultset.

Nowrunthequerybelow.

SELECT*

FROMCustomers

WHERE(ContactTitle=‘Owner’

ANDCountry=‘USA’)

ORCountry=‘Mexico’

Thisgivesadifferentresult. ThistimeyoustillgetalltheUScustomerswhereyour contactistheowner,butyourgetalltheMexicancustomersregardlessofwhatisintheir “ContactTitle”field. Thisisbecausethe“AND”operationbetweenthetoptwo comparisonsnowhappensfirst.

Allthathaschangedintheabovequeryisthepositionofthebrackets,butthisaffects

whatyouareaskingthequerytodo,whichchangestheresult.

Thenextfewexercisesareaboutputtingtogetherasimilarquery,onestepatatime.

Exercise–4.5

(answer)

GetalistofcustomersoutsidetheUS(the“notequalto”operatoris“<>”).

Exercise–4.6

(answer)

Getalistofcustomerswhereyourcontacthasatitlebeginningwith“Sales”or

“Marketing”.

Exercise–4.7

(answer)

Combinethetwoqueriesabove-getalistofthenamesandphonenumbersofyournon-

UScontactswiththose“Sales”and“Marketing”titles. Includetheirtitlesandcountriesin theresultstoo,soyoucancheckeasilywhetherthequeryisworkingcorrectlyornot.

NOT–Sayingwhatyoudon’twant

SupposeyouhaveworkedthroughyourlistofUSandMexico-basedowners. Nowyou wantalistofyourotherUSandMexico-basedcontacts. Youcouldusethequerybelow.

SELECT*

FROMCustomers

WHEREContactTitle<>‘Owner’

AND(Country=‘USA’

ORCountry=‘Mexico’)

Youcouldalsousethis:

SELECT*

FROMCustomers

WHERENOTContactTitle=‘Owner’

AND(Country=‘USA’

ORCountry=‘Mexico’)

Thereisnodifference. The“NOT”operatorreturnstheoppositeofacomparisonresult:

trueforfalseandfalsefortrue. Usingitabovewith“=”isthesameasusing“<>”.

However,theadvantageofthe“NOT”operatoristhatitcanbeappliedtomultiple comparisonsatonce,i.e.tothoseinbrackets. Forexample:

SELECT*

FROMCustomers

WHEREContactTitle=‘Owner’

ANDNOT(Country=‘USA’

ORCountry=‘Mexico’)

ThisqueryretrievestherecordsforownersbasedoutsidetheUSandMexico.

Exercise–4.8

(answer)

Getalistofthenamesandnumbersofyournon-UScontactswhosetitlesdon’tbeginwith

“Sales”or“Marketing”.

Exercise–4.9

(answer)

GetalistofthenamesandnumbersofyourcontactsoutsideoftheUSandMexico,whose

titlesdon’tbeginwith“Sales”or“Marketing”.

DISTINCT-Howtoremoveduplicates

Runthequery:

SELECTDISTINCTTitle

FROMEmployees

The“DISTINCT”keywordmakesaqueryremoveduplicatevalues. Intheexample,you mayhaveseveralemployeeswiththesamejobtitle,butthisquerywillreturneachtitle onlyonce. Itgivesyoualistofthejobtitlesthatexistinthecompany.

Exercise–5.1

(answer)

Listthecountriesinwhichyoursuppliersarebased.

ORDERBY-Howtosortyourrows

Ifyourunaquerylikethis:

SELECT*

FROMProducts

Youwillgettherecordsintheordertheyarestored,i.e.thosewithlowerProductID valueswillbenearerthetopoftheresults. However,youmaywantthemordered differently.

Ifyouwanttoeasilycomparehowmanyofeachitemyouhaveinstock,youcouldsort

yourqueryaccordingtothevaluesinthefield“UnitsInStock”,asbelow.

SELECT*

FROMProducts

ORDERBYUnitsInStock

Thisgivesyoualistwiththeleast-stockeditemsatthetop. However,itwouldprobably bemoreusefultohavethemost-stockeditemsatthetop,asthesearelikelytobemore importanttothecompany. Changethequeryto:

SELECT*

FROMProducts

ORDERBYUnitsInStockDESC

Thiswillsorttherowsindescendingorderofthe“UnitsInStock”values. Thedefault orderisascending,sothisquerygivesyouthereverseorderoftheoneabove.

Next,getthetopthousandrowsofthetable(asyoudidnearthestartofthisbook)and noticehow,towardsthebottom,thesupplierIDsarenotgroupedtogether. Supposeyou wanttoseeproductsfromeachsuppliertogether. Runthisquery:

SELECT*

FROMProducts

ORDERBYSupplierID

NoticehowrowswiththesamesupplierIDarenowalwaysnexttoeachother.

Ifyouwanttoorderyourqueryresultsbymorethanonefield,youcanusecommas,

i.e.run:

SELECT*

FROMProducts

ORDERBYSupplierID,UnitsInStockDESC

Noticehowthisquerysortsrowsbytheleftmostfield,“SupplierID”,first,sothatrecords

withthesameSupplierIDformblocksofrecords,andthensortsrowswithineachblock

bytheir“UnitsInStock”value. Alsonotethatthe“DESC”keywordhasbeenappliedto theorderingof“UnitsInStock”only,i.e.ithasbeenappliedonlytothefielditfollows,not thewhole“ORDERBY”clause. The“SupplierID”columnisstillsortedinascending order.

Exercise–6.1

(answer)

Grouptheproductsbycategory,theninascendingorderofpriceperunit. Showthe productname,categoryIDandunitpriceinyourresults.

TOP-Howtotakeasmallsampleofrows

Atthestartofthisbook,youfoundtheProductstable,andselectedthetopthousand rows. Thisisausefulbuilt-inoptioninSQLServerManagementStudio. However,the SQLtodothesamethingisverysimple,andworthknowing,sinceyoumaynotalways beusingSSMSanditsbuilt-inoptions. Runthequerybelow:

SELECTTOP1000*

FROMProducts

ThiswillreturnthefirstthousandrowsselectedfromtheProductstable. Iftherearefewer thanone-thousandrows,itwillreturntherowsthatarethere. Ifyoudon’twanta

thousandrows,justchangethe“1000”tothenumberofrowsyoudowant.

Oneadvantageofusing“TOP”toselectasmallnumberofrowsisthatselectingmore rowstakesmoretime. Thecomputertakestimetoloadthemall. Whywait?

Itisworthknowingthat“TOP”getsyouthefirstrowsselected,ratherthanthefirst thousandrowsstoredinthetable. Itallowsyou,shouldyouwish,torunquerieslikethis:

SELECTTOP10*

FROMProducts

ORDERBYProductName

Youcanthenviewadifferentsampleofrecords,inthiscasethetoptenproducts,ordered alphabeticallybyname. Therowsareputinorderbeforethetoptenaretaken.

Exercise–7.1

(answer)

Listthenamesandpricesofthetencheapestproducts.

Bottom

Asthereisa“TOP”,youmightexpecttheretobea“BOTTOM”. SQLServerdoesn’t havethis,butyoucanoftenstillgetthelastrowsofatable. TheProductstablehasa ProductIDfield,containinganIDnumberwhichincreases,byavalueofone,foreach newrecordadded,toensuretheIDfieldisuniqueforeachrecord. Knowingthis,toget thebottomtenrows,youcanuse:

SELECTTOP10*

FROMProducts

ORDERBYProductIDDESC

Thiswillsortthedatainthereverseordertohowitisstored. Effectively,thismakesan upside-downversionofthetable,andreturnsthetoptenrows,whichwereatthebottom oftheoriginaltable,fromthat.

GROUPBY-Howtosummariserowdata

Wehavealreadycoveredhowtodocalculationswithinasinglerecord. Youcouldnow, forexample,calculatethestockvalueheldforeachtypeofproductbyrunning:

SELECTUnitsInStock*UnitPriceASValueInStock

FROMProducts

However,ifyouwanttoknowthetotalvalueofstockinthewarehouse,thisquerystill leavesyouwithalotofaddinguptodo. Whatyouneedisawaytodocalculationsusing wholecolumnsasinput. Let’slookathowtodothat.

Sum

Runthefollowingquery.

SELECTSum(UnitsInStock)

FROMProducts

The“Sum”functionaddsallthevaluesinthenamedcolumnandgivesatotal.

Togetthetotalvalueofthestockheld,runthequery:

SELECTSum(UnitsInStock*UnitPrice)

FROMProducts

Operationsinsidefunctionbracketsarenodifferentfromoperationsinsideanyother brackets,inthattheyarecompletedfirst. Here,thismeansthat,foreachrow,thevaluesin thetwofieldsaremultiplied,andalloftheresultsarethenaddedtogetherbythe“Sum” function.

Aggregatefunctions

The“Sum”functionisknownasanaggregatefunction,becauseitbringstogether

(aggregates)alloftheinputfield’svaluesintoonevalue,whereasfunctionslike“IsNull”

arein-line,or“scalar”functions,becausetheyworkwithinrows,ratherthanacrossthem.

Thereareotheraggregatefunctionsthan“Sum”,suchastheoneinthequerybelow:

SELECTCount(*)

FROMProducts

ThissimplyreturnsthenumberofrecordsintheProductstable.

Togetthehighest(maximum)valueinacolumn,youcanuseaquerysuchas:

SELECTMax(UnitPrice)

FROMProducts

Togetthelowest(minimum)value,use:

SELECTMin(UnitPrice)

FROMProducts

Ofcourse,thequeryabovedoesn’ttellyouwhatthelowest-pricedproductactuallyis. To gettheproductnameaswellasthelowestprice,wecoulduseasubquery. We’llcover subquerieslater;theyhavetheirownchapter.

Youcanmakeyourqueryfilterrecords,beforeaggregatingthem. Thisallowsyouto workwithpartsofatable,suchastherecordsofproductsinaparticularcategory,orof producttypeswhichyoucurrentlyhaveinstock.

Thequerybelowdoesthelatter:

SELECTCount(*)

FROMProducts

WHEREUnitsInStock>0

The“WHERE”clauseisappliedtothequerybeforetheresultsarecounted.

Exercise–8.1

(answer)

Findthetotalnumberofunitsyouhaveinstockfordiscontinuedproducts(thesehavea

“1”,meaning“true”,intheir“Discontinued”field).

Exercise–8.2

(answer)

Findthetotalnumberofunitsyouhaveinstockforproductsinbeverages(CategoryID

=1).

OtherAggregateFunctions

ThereareotheraggregatefunctionsinSQL. Forexample,“Avg”calculatestheaverage valueofagroupofresultsfromanumbercolumn. However,theyareallusedinthesame waywithinqueries,soratherthanjustcovermoreaggregatefunctions,thiscoursewill nowfocusonmoreadvancedwaysofusingaggregation.

Grouping

Thelastexercisereturnedonefigureforonecategory. However,ifyouwantedtoseethe totalsforeverycategory,youwouldnotwanttohavetorunaqueryonceforeachof them. Thisiswheregroupingisuseful. Runthequerybelow.

SELECTCategoryID,Sum(UnitsInStock)ASUnitsInStock

FROMProducts

GROUPBYCategoryID

The“GROUPBY”clausetellsthequerytoapplytheaggregatefunction,inthiscase

“Sum”,torowswiththesamevaluesintheircategoryfields,sothequeryreturnsaresult

foreachcategory.

Toreturnfieldsinaquerywithgrouping,thosefieldsmusthaveonlyonepossiblevalue foreachgroup. Inthiscase,the“CategoryID”fieldhasonlyonepossiblevalueperrow, becauseit’sinthe“GROUPBY”clause. ThattellsthequerytoputeachcategoryIDin itsowngroup. The“Sum”fieldhasonevaluepergroup,whichitgetsbyaddingupall the“UnitsInStock”valuesinthecategory.

However,ifwewantedtoinclude“ProductName”inthe“SELECT”clauseofthisquery wecouldn’tdoit,becausetherearemanyproductnamesforeachcategory. Withmany possiblevalues,thequerycannotreturnanyofthem.

Exercise–8.3

(answer)

Getthenumberofunitsonorderfromeachsupplier. ShowthesupplierIDsinyour results.

UsingIDfieldslimitstheusefulnessoftheresultstoanyonewishingtoreadthem. However,youcangetthenamesassociatedwiththoseIDsinyourresults. We’llcover howtodothatinthechapteroninnerjoins.

Exercise–8.4

(answer)

Getthetotalvalueofthoseunits,foreachsupplier.

Exercise–8.5

(answer)

Getthepriceofthemostexpensiveitemineachcategory.

Exercise–8.6

(answer)

Getthepriceofthecheapestitemfromeachsupplier.

Groupingbymultiplefields

Itisalsopossibletogroupbymorethanonefield,asbelow.

SELECTSupplierID,CategoryID,Count(*)ASProductCount

FROMProducts

GROUPBYSupplierID,CategoryID

ORDERBYSupplierID,CategoryID

Thisqueryshowshowmanyproductseachsupplierprovidesineachcategory.

HAVING-Howtogettherowsyouwant,aftersummarising

Supposewewantalistofcategoriesthatcontainlessthantenproducts. Toseehowmany itemseachcategorycontains,wecoulddothis:

SELECTCategoryID,Count(*)

FROMProducts

GROUPBYCategoryID

Atthispoint,itlooksliketheresultscouldbefilteredbyapplyinga“WHERE”clauseto the“Count(*)”field. However,the“WHERE”clauseisappliedtothefieldsofthetable inthe“FROM”clausebeforetherowsarecounted. Itcan’tfilterbyacountthatdoesn’t existyet.

Tofilterbyaggregatevalues,suchasthosein“Count(*)”above,youcanuse“HAVING”. Itworkslike“WHERE”,butforaggregatedvalues. Runthequerybelow.

SELECTCategoryID,Count(*)

FROMProducts

GROUPBYCategoryID

HAVINGCount(*)<10

Nowyoushouldseetheresultsyouneed.

Thecountisincludedinthe“SELECT”clauseabovebecauseithelpsconfirmthatthe resultsarecorrect. However,ifyouwantedjustthelistofcategories,youcouldleaveout thatpartofthequery,asbelow.

SELECTCategoryID

FROMProducts

GROUPBYCategoryID

HAVINGCount(*)<10

The“SELECT”clausespecifiesdatatodisplay. The“HAVING”clausespecifiescriteria forexcludingdata. Youdon’thavetodisplaydatainyourresultsinordertofilterthemby it:youonlyneedtheaggregatecalculationinthe“HAVING”clause. Fortheexercises below,however,youmaywishtoincludetheaggregatecolumnsintheresultsyoudisplay, soyoucanmoreeasilyseewhetheryourqueriesworkasintended.

Exercise–9.1

(answer)

ListtheIDsofcategorieswithmorethan100unitsinstock.

Exercise–9.2

(answer)

ListtheIDsofsupplierswhichhaveonlyoneproduct.

Exercise–9.3

(answer)

Listthecategorieswhichdon’thaveunitsonorder.

Applyingthistoothertables

Takealookatthe“Orders”tabletoseewhatdataisspecifictoeachorder:ithasonerow perorder,andtherefore,auniqueorderIDforeachrow. Nowtakealookatthe“Order Details”tabletoseedataspecifictoeachproductineachorder,ithasonerowperproduct perorder. Inoneorder,therecanbemanyproducts,sointhe“OrderDetails”table,there canbemanyrowswiththesameorderID. Thisisknownasaone-to-manyrelationship betweenthetables,orrather,therecordsinthem.

Groupingandaggregationareusefulfordealingwithdataorganisedthisway. To completethefollowingexercises,groupandaggregatethedataintheOrderDetailstable.

Notethatwhenreferringtothetable,youwillneedtousetheformat:

FROM[OrderDetails]

Thesquarebrackets“[]”tellSQLthatthetextwithinthemisallonename,despitethe

spaceinthemiddle.

Exercise–9.4

(answer)

Listtheorders(byID)containinglessthanfiftyunits.

Exercise–9.5

(answer)

Getalistofordersinwhichanyoftheproductshavebeendiscountedbymorethan20%

(0.2). Showoneofthesehigher-than-20%discountsforeachorder.

Multipleaggregatefunctions

Youcanusemorethanoneaggregatefunctionatatime,e.g.

SELECTOrderID,Count(*),Sum(Quantity)

FROM[OrderDetails]

GROUPBYOrderID

This(slightlycontrived)exampletellsyouboththetotalnumberofproductsandthetotal

numberofunits,ineachorder.

Exercise–9.6

(answer)

Getalistoforders,theircashvalues(beforeanydiscount)andthenumberofunitsthey contain. Addyourowncolumntitlestothequeryresult.

Alias-Howtoquerywithlesstyping

ColumnAlias

Analiasisanalternativename,ofyourchoice,foratableorcolumn. Youhavealready usedaliasesseveraltimestorenamethecolumnheadingsastheyappearedinyourquery results,e.g.

SELECTContactNameASContact

FROMCustomers

Youdon’thavetousethe“AS”keywordatall. Removethe“AS”andrunthequery again.

SELECTContactNameContact

FROMCustomers

Thisgivesexactlythesameresult. However,thequerywith“AS”initisclearertoread. Theextrawordmakesthefactthatyouareusinganaliasmuchmoreobvious.

TableAlias

Inthecomingchapterscoveringjoins,wewillrunqueriesonmultipletablesatonce. This createsaproblemforSQLinthat,iftwotableshavethesamefieldname,andyouask yourquerytogiveyouthatfield,SQLdoesn’tknowwhichtableyouwanttotakethefield from. Ifyouevertrytorunaquerywherethisisanissue,youwillgetanerrormessage tellingyouthatthefieldnameyourequestedis“ambiguous”. SQLsolvesthisproblemby lettingyouspecifythetablenameofthefieldyouneedaswell. Wecanseehowthis works,evenwithonetable.

SELECTCustomers.CustomerID,Customers.CompanyName

FROMCustomers

WHERECustomers.CustomerIDLIKE‘A%’

Althoughwedon’tneedtospecifyatablewhenthereisonlyone,thisexampledoesshow howatableisspecified(beforethefieldname,separatedfromitbya“.”). However,it alsoshowsthatthiswayofspecifyingtablesisinconvenientlylongtotypeout,orevento readthrougheasily. Thequerymightcontaintwentyfields,inthe“SELECT”clause,five moreinthe“WHERE”clause,andtakedatafromfivedifferenttables. Suchaquery quicklybecomesunreadableandtedioustotype,evenwithcopyandpaste. Thismakesit hardertounderstand,ortore-usebychangingitscode. SQLsolvesthisproblemby allowingtheuseofaliasesontablenames,toshortenthem,asbelow.

SELECTc.CustomerID,c.CompanyName

FROMCustomersc

WHEREc.CustomerIDLIKE‘A%’

Thisqueryreturnsanyrecordsinthe“Customers”tablewhichhavea“CustomerID”field beginningwith“A”. The“c”isthealiasforthecustomertable. Thetablealiasismade byputtingthealiasname(“c”)aftertherealtablename(“Customers”)inthe“FROM” clause. Ifyoutakethispartaway,asbelow,thequeryfailstorun.

SELECT*

FROMCustomers

WHEREc.CustomerIDLIKE‘A%’

Inqueriesusingasubquery,join,orboth,theuseoftablealiasescansavetimeandmake

iteasiertoreadthroughaqueryyoujustwrote.

INNERJOIN-Howtocombinerelatedrecordsfrom

differenttables

Innerjoinsreturnalistofmatchingrecords. Typically,theyaremadebyjoiningtwo tablesontheuniqueIDfieldofone,suchastheIDfieldoftheRegiontable,anda referencetothatfieldintheothertable.

Asanexample,runthequerybelow:

SELECT*

FROMRegion

INNERJOINTerritories

ONRegion.RegionID=Territories.RegionID

Notethattheresultofthisqueryisfifty-threerows,thesameasthenumberofterritories.

Eachterritoryhasonlyoneregion(theregionitisin)andthatistheregionthatappears

nexttoitintheresults.

Wecanshortenthequerybyusingtablealiases,asbelow:

SELECT*

FROMRegionr

INNERJOINTerritoriest

ONr.RegionID=t.RegionID

Sofar,wehaveused“*”togetalloftherowsfrombothtables. Thisisjustforsimplicity, however. Ifwewanttolimitthenumberofcolumnsreturned,wecan. Trychangingthe “SELECT”clauseoftheshortenedquerytoeachofthosebelow,andthenrunningit again.

SELECTt.TerritoryDescription,r.RegionDescription

Thisgivesusthespecifiedcolumns,onefromeachtable. Notethatwehavealsousedthe aliases“r”and“t”tospecifywhichtablestotakethecolumnsfrom. Wedon’talways needtodothis,butitisgoodpractice. Ifanyofthecolumnnameswewantedtoselect appearedinbothtables,andwedidn’tusethealias,thenSQLwouldnotknowwhichone topick,andwouldreturnanerrormessage.

Nowtryrunningthequerybelow:

SELECTt.*,r.RegionDescription

And:

SELECTt.TerritoryDescription,r.*

Youwillseethatthefirstversionabovereturnstwocolumns,thenextreturnsallthe

columnsfromTerritories(andonefromRegion)andthelastreturnsallcolumnsfrom

Region(andonefromTerritories).

Exercise–11.1

(answer)

Returnalistofproductsandtheircategorynames. IncludeallcolumnsfromtheProducts tableandonlythecategorynamecolumnfromtheCategoriestable.

Exercise–11.2

(answer)

Returnalistofordersandthenamesofthecompanieswhichplacedthem.

Exercise–11.3

(answer)

Earlier,inthechapteronthegrouping,therewastheexercise(8.3)below:

Getthenumberofunitsonorderfromeachsupplier. ShowthesupplierIDsinyour results.

OnlythesupplierIDwasshownintheresults. Hereisthequerythatanswersthat exercise.

SELECTSupplierID,Sum(UnitsOnOrder)

FROMProducts

GROUPBYSupplierID

Nowthatwehavecoveredjoins,youknowenoughtoreplacethesupplierIDwiththe suppliername. Tryit. Ifyoucan’tworkouthowtodothis,thenjustusetheanswerto thisexerciseasanexample,andthenextexercisewillgiveyouanotherchancetoputthis techniqueintopractice.

Exercise–11.4

(answer)

Alsointhechapteronthegrouping,therewastheexercise(8.5)below:

Getthepriceofthemostexpensiveitemineachcategory.

Thequerywas:

SELECTCategoryID,Max(UnitPrice)

FROMProducts

GROUPBYCategoryID

Canyoumakeitreturntheresultswiththecategorynames,insteadoftheIDs?

Otherwaystojoin

Youcanjointablesinmorewaysthantheoneshownabove. Youcanusean“AND”in your“ON”condition,toonlyjointableswithtwomatchingsetsoffields. Youcanusethe multiple“JOIN…ON…”clauses,oneaftertheother,tojoinmultipletablestogether. Youcanjointablesonotherconditionsthanafieldinonematchingafieldintheother.

Althoughjoinsareusuallymadeonconditionofafieldfromeachtablehavinganequal valuetotheother,youcanjointableshoweveryoulike. Youcanjoinrecordsonthebasis thatthevaluesarenotequal,“<>”,ifyouwant. However,youaremorelikelytojoinon somethinglikeadatefield,wherethedatesarethesame,butthetimesarenot. For example,ifyoulookintheOrderstable,youwillseethatthedatesdonotincludetime values,apartfrom“00:00:00.000”i.e.midnight. Thetimetheorderswereplacedisinfact notbeingrecorded. Ifyouweretryingtojointhistabletoatablewhichhaddateswiththe timesrecordedtoo,youcoulduseanoperatorlike“BETWEEN”,a”>=”conditionjoined by“AND”toa“<”conditiontosimulatebetween,orsomewayofroundingthefieldwith thetimevalue. The“ON”clause,likethe“WHERE”clause,isafilter. Itisasmallstep fromusing“WHERE”tousing“ON”.

OuterJoins–Howtogetunrelatedrecords

Theproblemwithinnerjoins

Beforecoveringouterjoins,weneedanexampletohighlightthelimitationsofinnerjoins.

We’lltakeourexamplefromtheresultsofthequerybelow,sorunitbeforereadingon.

SELECT*

FROMCustomersc

INNERJOINOrderso

ONc.CustomerId=o.CustomerId

Yourresultstablewillincludealistofalltheordersinthedatabase,alongsidetherecords ofthecustomerswhichmadethem. Notethatthecustomerrecordpartofeachrowis duplicateddowntheresultstable. Eachcustomermaymakeseveralorders,soone customerrecordwillbematchedtoseveralorderrecords,andduplicatedforeachof them. Eachorderhasonlyonecustomer,however,soonlyappearsonceinthequery result. Youcanconfirmthisbycheckingtheordertablecontents:itwillhavethesame numberofrowsasyourqueryresult.

Allordersareaccountedfor:sofar,sogood.

Supposeyouarenowlookingthroughthelistforaparticularcustomerandyoucan’tfind them. YouknowtheyareintheCustomerstable. Hassomethinggonewrongwithyour query?

Inthenextexercise,checkthatallofthecustomersareonthelisttoo. You’llneedaway togetalistofdistinctcustomernamesfromtheresult,soyoucancompareittothe recordsinyourcustomertable. Fortunately,wealreadycoveredthekeyword (“DISTINCT”)thatletsyoudothat.

Exercise–12.1

(answer)

Getalistofthecompanynamespresentinyourqueryresult(noduplicates).

Whatitallmeans

IfyoucomparethelisttoyourCustomerstable,evenjustbythenumberofrowsineach, youwillseethatthelistismissingacoupleofrecords. Ifyouweretotakethecustomer IDsofthoserecords,andsearchforthemintheOrderstable,youwouldn’tfindthem. Theyarenotthere. Thosecustomershavenoorders.

Thisisalsowhytheydon’tappearinthequeryresult. Thejoindependsoncustomersand ordershavingmatchingcustomerIDs. Iftherearenoordersforaparticularcustomer,the customerrecordcannotmatchanythingandisneverincludedintheresultsatall.

Inthissampledatabase,thesekindsofsituationsarehardtofind. Intherealworld,they arecommon. Herewehavetwocustomerswhohaveneverplacedorders. Maybethey arenewcustomers.

Anothercommon,real-worldexampleofonetablehavingunmatchedrecordsinanother wouldbeintablesofsalesororders,andrefundtables. Ifasaleisrefundeditwouldhave amatchingrecordintherefundstable;ifnotrefunded,therewouldbenorefundandno record. Therefore,doinganinnerjoinonthetwotableswouldresultinalistofrefunds, andtheirsales,butnottheun-refundedsales.

LeftOuterJoins

ComingbacktoourqueryinNorthwind,ifyouneedtoseetheunmatchedrecordstoo,

youuseadifferenttypeofjoin:anouterjoin,asbelow:

SELECT*

FROMCustomersc

LEFTOUTERJOINOrderso

ONc.CustomerId=o.CustomerId

Youmaynoticefromtherowcountthatthisquerygivesyouaslightlylargersetof results. Itnowincludesthetwocustomerrecordsyouweremissingbefore. Let’smakeit morespecific. Adda“WHERE”clause,asbelow,andrunitagain.

SELECT*

FROMCustomersc

LEFTOUTERJOINOrderso

ONc.CustomerId=o.CustomerId

WHEREo.CustomerIdISnull

Thistime,youwillonlyseetworecords:theunmatchedcustomerrecords,alongsidethe Orderstablecolumns. TheOrderscolumnswillbefullofnullvalues,asthereisnoorder datatoputinthem.

Anouterjoinincludesunmatchedrecordsinthequeryresult. Aleftouterjoinincludes unmatchedrecordsfromthelefthandtable. Thiswillbetheonebeforethe“JOIN” keywordinthequery,i.e.thetablenametotheleftof“JOIN”ifthequeryiswrittenallon oneline. Inthiscase,it’stheCustomerstable.

RightOuterJoins

Arightouterjoindoesthereverseoftheleftouterjoin. Itincludesunmatchedrecords fromtherighthandtablei.e.thetablespecifiedafterthe“JOIN”inthequery,inthiscase, theOrderstable. Toseehowthisworks,edityourquerytomakeitintotheonebelow. Thetablenameshavebeenswapped,butthejointypehasbeenchangedtoo,sothequery willstillreturnunmatchedrecordsfromtheCustomerstable. Runthequerynow.

SELECT*

FROMOrderso

RIGHTOUTERJOINCustomersc

ONc.CustomerId=o.CustomerId

WHEREo.CustomerIdISNULL

Youwillseetworows,asbefore. Scrolltotherightoftheresults,andyouwillseethe customerfields,totherightoftheorderfields. Theresultsareidentical,apartfromthe tablecolumnsbeingswappedlefttoright,andifyoureallywantedthecolumnsinthe originalorder,youcouldspecifythatwith“SELECTc.*,o.*”. Therefore,youdon’tneed touserightouterjoinsatallifyoudon’twantto,becausealeftouterjoincandotheall thesamethings.

InnerJoinsvs.OuterJoins

Let’scontinuewithleftouterjoins. Changethelastquery,sothatitusesaleftouterjoin (andno“WHERE”clause)asbelow:

SELECT*

FROMOrderso

LEFTOUTERJOINCustomersc

ONc.CustomerId=o.CustomerId

Runthequery. ThistimetheOrderstableisontheleftsideoftheleftjoin. Thequery willreturnalltheorders,includingorderswithoutcustomers.

Nowaddthislinetotheendofthequery:

WHEREc.CustomerIdISNULL

Thiswouldreturnonlytheorderswithoutcustomersmatchedtothem. Itreturnsno results,soweknowtherearenosuchorders. Therearenoorderswithoutcustomers, whichistobeexpectedasthatshouldnotbepossible.

Inthiscase,thequery(withorwithoutthe“WHERE”clause)returnsthesameresultsasit

wouldwithaninnerjoin.

Exercise–12.2

(answer)

Thereisatablecalled“EmployeeTerritories”whichshowswhichterritoriesareassigned towhichemployees. Writeaquerythatreturnsalltheterritories,andtheIDofany employeeassignedtothem.

Exercise–12.3

(answer)

Someoftheterritoriesdonothaveassignedemployees. Changethequerysothatitonly returnsresultsforthoseterritories.

Exercise–12.4

(answer)

Changethequerysothatitreturnsonlyresultsforthoseterritoriesthatdohaveemployees assigned. Makesureyouchecktheanswerforthis,evenifyouthinkyourresultsare correct.

Exercise–12.5

(answer)

Changethequerysothatitshowsthenamesofthoseemployeesalongsidetheterritory

description. Rememberthatyoucanjoinmoretablesjustbyputting“…JOIN…ON…” statementsoneaftertheother,intheformat:

FROMTableXASx

INNERJOINTableYASy

ONx.FieldA=y.FieldA

INNERJOINTableZAsz

ONy.FieldB=z.FieldB

FullOuterJoins

Itisevenpossibletoreturnunmatchedrecordsfrombothsidesofthejoinatonce,by using“FULLOUTERJOIN”. Itisprobablyfairtosaythatthesearenotcommonlyused. Indeed,somesystems,likeMicrosoftAccess,don’tsupportfullouterjoinsatall.

Self-Join-Howtojoinatabletoitself,andwhyyouwould

wantto

TheEmployeestableisabitdifferentfromtheothertables:itreferencesitself. Employeesreporttootheremployeeswithrecordsinthesametable. Ifyouwantedto,for example,seealistofemployeesnexttotheirmanagersnames,youwouldneedtojointhe tabletoitself. Thisiscalledaself-join. Ofcourse,atablecan’treallybeintwoplacesat once,sowhatwedoisjointwo(temporary)copies,or“instances”,ofthetable. Weuse “AS”aliasestomakeastaffcopyandamanagercopy. Wethenjointheseaswewould anynormalpairoftables.

Toseehowitworks,runthefollowingquery:

SELECTstaff.FirstName+‘‘+staff.LastNameASStaff,

boss.FirstName+‘‘+boss.LastNameASBoss

FROMEmployeesstaff

INNERJOINEmployeesboss

ONstaff.ReportsTo=boss.EmployeeID

Notethatonlyeightofnineemployeesappearintheresults. Oneemployee(theheadof thecompany)doesn’treporttoanyone,soisn’tshown.

Exercise–13.1

(answer)

Useanouterjointomakethatemployeeappear.

CrossJoin–gettingallpossiblecombinationsoftablerows

Beforestartingonthistopic,Ishouldpointoutthatthistypeofjoinisnotcommonlyused, andyouwon’tneedtoknowaboutittounderstandthelaterchapters. Youcouldskip thesefewpages,andjuststartthenextchapter:“UNION/UNIONALL”. However,cross joinsareeasytodo,helpshowhowjoiningtablesinSQLactuallyworks,anddohave somepracticalvalue,sotheyareincludedhereforanyoneinterested.

Introducingcrossjoins

Acrossjoinisthesimplesttypeofjoin. Itisthejoinyoumakewhentherowsinyour tablesdon’tneedtoreferenceeachother. TheNorthwinddatabasedoesn’thaveanysuch tables. Howeverwecanstillusethetablesitdoeshave,todemonstratehowcrossjoins work,beforeintroducingthesituationsinwhichyoumightwanttoactuallyusethem.

Let’stakealookatthetablestobeusedinthejoin. LookintheRegiontableandnoteits fourrows. LookintheTerritoriestableandnotethatithasfifty-threerows,eachwitha RegionIDfromonetofour. WecanconcludethatNorthwindoperatesinfourregions, whicharebrokendownintoacombinedtotaloffifty-threeterritories.

Howcrossjoinswork

Toseehowcrossjoinswork,runthisquery:

SELECT*

FROMRegion,Territories

Thisquerygivesyoualistoftwo-hundred-and-twelverows. Theserowscontainallthe columnsfrombothtables. Ifyouscrolldown,youwillseethateachofthefourRegion

IDshasaquarteroftherows,andifyoudothemath,youwillseethat4x53=212.

Thisquerygaveyoueverypossiblecombinationofrows,eachofthefifty-threeregions foreachofthefourterritories. Itdidn’tcheckthatthoseregionswereinthoseterritories, becausewedidn’ttellitto.

Joinscombinetwosetsofrows,andreturnanycombinationswhichmeetoneormore conditions. Intheinnerjoinwelookedatearlier,thatconditionwasthattheterritoryhasa RegionIDwhichmatchestheregion. Inacrossjoin,wewantallcombinations,soifwe wereforcedtouseacondition,wewoulduseonethatreturnedtrueforeverycombination ofrows. Toshowhowthisispossible,wecansimplyuseaconditionliketheoneinthe “WHERE”clauseofthequerybelow.

SELECT*

FROMRegion,Territories

WHERE1=1

Ifyourunthisquery,youwillseetheexactsameresultasbefore. Onealwaysequalsone, sotheconditionisalwaysmet.

Thisquerygivesthesameresultsasacrossjoin,butthereisstillonemorethingweneed todotofullyshowhowcrossjoinswork. WeneedtousetheactualSQLjoinclauseto writethequery. Thisissimpletodo,justreplacethecommabetweentablenameswith “JOIN”andreplace“WHERE”with“ON”.

SELECT*

FROMRegion

JOINTerritories

ON1=1

Runningthisquerygivesyoutheexactsameresultasbefore,butthistimeitisveryclear inyourquerythatyouarejoiningtables,andonwhatcondition. Allotherjoinsuse variationsofthequerysyntaxabove,simplyaddingthetypeofthejoinbeforetheword “JOIN”,e.g.inner,leftouter,rightouter,fullouter.

Ifwewantedtomakethisaninnerjoin,wewouldsimplyput“INNER”before“JOIN” andchangethefilterinthe“ON”clause. Becausethe“ON”clause,likethe“WHERE” clause,isjustafilter.

Usesofcrossjoins

Supposeyouhavealistofdatesandalistoftimeslots,eachintheirowndatabasetable. Maybetheyarethedatesandtimesofperformancesinatheatre. Youwantalistofall possibledateandtimecombinations. Youneedacrossjoin.

Supposeyourtheatrehastwentyrows,fromAtoT,andtwentyseatsineach,from1to

20. Youhave,orcaneasilymake,atablewithalistofrowsin,andanotherwithalistof seatnumbers. Youcanuseacrossjointomakeallcombinationsofrowandseatnumber:

A1,A2…B1,B2…etc. Youthenhavealistoftheseatsavailableforaperformance.

Supposeyouwanttocombineyourlistofseatswithyourlistoftimeslotstogeneratea listofticketsyoucansell. Again,youneedacrossjoin.

Exercise–14.1

(answer)

UseSQLtocalculatehowmanycombinationsofrowstherewouldbeiftheShippersand

Customerstableswerecross-joined.

Exercise–14.2

(answer)

Actuallyjointhetwotables.

Exercise–14.3

(answer)

UseSQLtocounthowmanyrowstheresulthas.

UNION/UNIONALL-Howtocombinerowsfromtwo

tables

UNIONALL

Sometablesarenotrelatedtoeachotherinthesensethattheycanbecross-referencedby, forexample,comparingfieldscontainingIDnumbers. Joiningthemmaynotmakesense. However,theymaystillhavethingsincommon,andyoumaywanttoquerythem togetherbecauseofthis. Forexample,youmaywantalistofthecities,orcountries, whereyouhavetradingpartners,i.e.suppliersorcustomers. Howeverthesearelistedin twodifferenttables. Itwouldbeusefultohaveawaytoaddthetables’rowstogether. Thereisaway,asshownbelow:

SELECTCompanyName

FROMSuppliers

UNIONALL

SELECTCompanyName

FROMCustomers

The“UNIONALL”statementaboveaddstheresultsoftheCustomersqueryontothe bottomoftheresultsoftheSuppliersquery. Younowhaveallthenamesinonelist.

However,thisresultdoesn’tshowyouwhetherthecompaniesarecustomersorsuppliers.

Trythisinstead:

SELECTCompanyName,‘Supplier’ASCompanyType

FROMSuppliers

UNIONALL

SELECTCompanyName,‘Customer’

FROMCustomers

Thestringliteralsnowtelluswhichquery,andthereforewhichtable,therowscame from. Weonlyneedthe“AS”partinthetopquery,becausethecolumncanonlyhaveone title.

Notethatfor“UNION”towork,eachfieldinthetop“SELECT”clausemusthaveafield ofthesametypedirectlybelowitinthelower“SELECT”clause. Youcouldnot,for example,makeaunionofthesupplierIDandthecustomercompanyname. Oneisa numberandtheothertext,soSQLwouldreturnanerror.

Exercise–15.1

(answer)

Changethequerytoalsoincludecountryandcityfields.

UNION

Thereisalsoa“UNION”keyword. Itworkslike“UNIONALL”,butitalsoremoves duplicaterows(i.e.rowswhereallthevaluesarethesameasthoseofanearlierrowinthe result)fromthecombinedsetofresults,whereas“UNIONALL”doesn’t.

Forexample,thequerybelowuses“UNIONALL”

SELECTCountry

FROMSuppliers

UNIONALL

SELECTCountry

FROMCustomers

Ifyourunthis,youwillseesomecountriesappearseveraltimes. Ifyoudeletethe“ALL” fromthequeryaboveandrunitagain,youwillseethatthelistnowcontainsdistinct values,noduplicates. Changethequerytotheonebelow,andrunit.

SELECTCountry,‘Supplier’

FROMSuppliers

UNION

SELECTCountry,‘Customer’

FROMCustomers

Notethatalthoughyounowseesomecountriesappeartwice,thisisonlybecausetheir

rowshavedifferentvaluesinthesecondcolumn,sotherowsasawholearenot

duplicated,and“UNION”leavesthemin.

Thereareotherwaystocombinetworesultsets,whichwillbecoverednext,but

“UNION”and“UNIONALL”areprobablythemostcommonlyused.

INTERSECT–Howtogetrowsthatareonlyinbothtables

Runthequery:

SELECTCountry

FROMCustomers

INTERSECT

SELECTCountry

FROMSuppliers

Youwillseealistofcountries. Thesearethecountrieswhichappearinbothtables. As with“UNION”,therearenoduplicaterowsintheresults;theyhavebeenremoved.

Also,aswith“UNION”,whenusing“INTERSECT”thenumberandtypeofrowsmust matchup. The“EXCEPT”clauseisthesame. We’llcoverthatnext.

EXCEPT–Howtogetrowsthatareonlyinonetable

Runthequery:

SELECTCountry

FROMCustomers

EXCEPT

SELECTCountry

FROMSuppliers

Youwillseealistofcountries. ThesearethecountrieswhereNorthwindhascustomers butnosuppliers. Again,duplicateshavebeenremoved.

Thiskeywordhasanotheruse. Itsletsyoucomparetwoqueryresultsandcheckifthey arethesame. If,duringanyexercise,youwroteaquerywhichdifferedfromtheonein theanswer,butwhichyoustillbelievewascorrect,nowisyourchancetotestwhetheryou wereright! First,makesureyourqueryhasthesamecolumns,inthesameorder,so “EXCEPT”doesn’tgiveyouanerror. Afterthat,simplyrunthefollowingSQL:

YourQueryHere

EXCEPT

AnswerQueryHere

Thisgivesyoutherowsyourqueryreturns(ifany)whicharedifferentfromthoseinthe correctanswer. Also,runthis:

AnswerQueryHere

EXCEPT

YourQueryHere

Thisgivesyoutherowsintheanswerwhicharemissingfromyourquery(again,ifthere

areany).

Iftherearenoresultsineachcase,thenyourqueryresultisidenticaltotheanswerquery

result,andthereforeyourqueryiscorrect(oratleast,itisgoodenoughthatitdoesn’t

produceanyerrorsusingthedataprovidedinNorthwind),so,welldone!

Sys/Metadata-Howtogetinformationaboutyour

database

TheNorthwinddatabaseisasmalldatabase. Ithasasmallnumberoftables,andthose havesmallnumbersofrowsandcolumns. Itissimple. Thetableandfieldnamesare self-explanatoryandpredictable. Databasesarerarelythissimpleintherealworld.

Youmayfindyourselfqueryingasystemcontaininghundredsoftables. Ifyouwantto findatable,andonlyhavearoughideaofwhatitsnameis,orshouldbe,youmayhaveto scanalistofhundredsofnames. Inthissituation,knowingjustalittleabouthowtoquery thesystem,ormetadata,ofadatabase,canbeahugetime-saver. Tryoutthefollowing query:

SELECTName

FROMSys.Tables

WHERENameLIKE‘%Demo%’

Thisreturnsalistoftablescontainingthestring“Demo”inthename. Ifyouright-click onthenames,youcancopythemforuseinnewqueries,e.g.youcouldselectthetopten rowsofaviewnamedintheresultsofthequeryabove.

Learningfromexistingviews

Databasesmayalsohavemany,maybehundreds,ofstoredqueries,knownas“views”, alreadymade. Ifmanypeoplerunqueriesfromyourdatabase,oneofthemmayalready havemadequeriesyoucouldusethatyoudon’tknowaboutyet.

Theviewsarelistedbelowtablesintheobjectexplorer(inthelefthandpanel). Ifyou wanttoseethequeriestheycontain,right-clickonthemandchoosetheoptions“Script Viewas”then“CREATEto”. ThiswillshowyoutheSQLtheviewuses. Therewillbe someextralinesofSQLatthetop,todowithsavingthequeryasaview,butfurtherdown youwillseethefamiliarSQLforgettingdata. Ifyouwanttoseesomeresultsforaview,

youcanusethe“SelectTop1000Rows”menuoptiononviewstoo.

Northwinddoesn’thavehundredsofviews,butwecanstilluseittoshowhowtosearch

largenumbersofviewsefficiently,asintheexercisebelow.

Exercise–18.1

(answer)

Canyouchangethequeryabovetodisplayalistofviewscontainingtheword“Product”?

Hint:takethequeryaboveandchangethewords“Tables”and“Demo”.

Subqueries-Howtomakeonequeryusearesultfrom

another

SubqueriesintheFROMclause

Thisfirstuseofasubqueryisoneofthesimplesttograsp. Supposeyouhavejustruna queryandwouldnowliketoperformafurtherqueryontheresultstableitgaveyou. Maybethefirstqueryisverylongandcomplex,fullofjoinsandcalculations. Maybeit waswrittenbysomeoneelseandyoudon’twanttoeditit. Youjustwanttopulloutthe datayouneedfromtheresultstable. Onewaytodothiswouldbetocreateaview (effectivelyasavedquery)inthedatabase. Liketheviewsinthelastchapter,thiswould haveaname,andyoucouldrefertothatnamethesamewayyourefertoatablename:in the“FROM”clauseofanyotherquery. Anotherway,whichsavesyoufromhavingto createaview,istoqueryyourqueryresultdirectly.

Wedon’tactuallyneedtomakealongcomplexqueryliketheoneimaginedabove. We canseetheprincipleeasilyinamuchsmallerexample. Runthecodebelowasyoufirst query.

SELECTProductName,UnitsInStock*UnitPriceASStockValue

FROMProducts

Nowsupposeyouwanttolistonlythoseproductswithastockvalueinthethousands.

Thefollowingqueryletsyoudosoverysimply,byaddingacoupleoflinestoeachendof

theoriginal.

SELECT*

FROM(

SELECTProductName,UnitsInStock*UnitPriceASStockValue

FROMProducts

)sq

WHEREsq.StockValue>=1000

Notethatthebracketsaroundtheoriginal,or“inner”,querymeanthatitwillbecompleted first. Itsresultswillbeusedintheouterquery,justlikeatablewouldbe. Inthisexample, wehavetheouterquerygivetheinnerquery’sresultthealias“sq”,for“subquery”,sothat wecanrefertoit. Theouterquerytakesonlytherowsfromtheresultstablewhichmeet theconditioninthe“WHERE”clause,anditdoessousingthe“StockValue”field,which thesubquerygenerated.

Thissavessomethinkingcomparedtomodifyingtheoriginalquery. Tofilteritthesame way,wewouldhaveneededtoaddthefollowingclausetotheoriginalquery:

WHEREUnitsInStock*UnitPrice>=1000

Withthesubqueryapproach,ontheotherhand,youcanrunthefirstquerywithout

readingitscodeanddesignyourouterquerysimplybylookingattheresultstableand

decidingwhichbitsyouneed.

Exercise–19.1

(answer)

Withoutchangingitssubquery,canyoumakethequeryabovereturnthecombinedstock

valueofalltheproductsyoustock?

Exercise–19.2

(answer)

AnotheruseforsubqueriesintheFROMclauseistoperformgroupingorsortingonthe resultsofaunion. UsetheSQLbelowasasubquery. Haveyourmainqueryreturnalist ofcountriesandcities,makingsureanyrowswiththesamecountryorcitystaytogether.

SELECTCompanyName,‘Supplier’ASCompanyType,City,Country

FROMSuppliers

UNIONALL

SELECTCompanyName,‘Customer’,City,Country

FROMCustomers

TheINoperator

The“IN”operatoriscommonlyusedinsubqueries,particularlysubqueriesinside “WHERE”clauses,butyoudon’tneedasubquerytouse“IN”. Youcanseeitseffect clearlybyrunningtheexamplebelow:

SELECTSupplierID,CompanyName,Country

FROMSuppliers

WHERECountryIN(‘UK’,‘USA’)

Using“IN”let’syoucheckifonevalue(e.g.thevalueinarecord’s“Country”field)

matchesanyofalistofvalues.

Toseealistofsuppliersfromothercountries,runthisquery:

SELECTSupplierID,CompanyName,Country

FROMSuppliers

WHERECountryNOTIN(‘UK’,‘USA’)

The“NOT”makesthequerycheckforcountrieswhicharenotonthelist.

SubqueriesintheWHEREclause–usingtheINoperator

Supposeyouneedalistofalltheproductssuppliedfromaparticularcountry. The Productstabledoesn’tsaywhichcountrysuppliesaproduct. Whatitdoessayisthe SupplierID,whichletsyoufindtherecordinthesuppliertableandfromthat,the supplier’s,andthereforetheproduct’scountry.

Still,yoususpectthatyouwillhavetoproducesimilarlistsinfuture,forothercountries. Youwantaquerythatyoucanre-usetogetthoseresults,justbychangingthecountry nameinyour“WHERE”clause. Thesubquerybelowisonewaytodothis.

SELECTProductName

FROMProducts

WHERESupplierIDIN

(

 

SELECTSupplierID

FROMSuppliers

WHERECountry=‘UK’

)

ThisshouldreturnalistofBritishsoundingfoods,andsomemoreexoticsounding liquids,presumablyimportstotheUKwhichthesupplierthenshipson. Ifyouchange “UK”toanothercountryname,youcangetasimilarlistforadifferentcountry

ThesubqueryreturnsalistofUKsupplierIDs,andthemainquery,whichreturnsthe

resultsyouactuallysee,givesyoualltheproductswithasupplierIDonthatlist.

Notetheuseof“IN”above. Thistellsthe“WHERE”clausetocheckifanyofthevalues inthesubquerymatchtheproduct’ssupplierID. Ifwehadusedthe“=”operator,thenwe wouldbelimitedtosubquerieswhichalwaysreturnasinglevalue,i.e.asingleSupplier IDcannotbeequaltoalistofSupplierIDs,andthissituationwouldcausethequeryto returnanerroranyway. Using“IN”letsusmatchalistagainstasinglevalue.

Exercise–19.3

(answer)

ReturnalistofproductssuppliedfromtheUKorUSA.

Exercise–19.4

(answer)

Makeaquerywhichreturnsalistofproductsintheseafoodcategory.

Exercise–19.5

(answer)

Makeaquerywhichreturnsalistofproductsfromonlythecategorieswhichyouare confidentwillbesuitableforvegetarians. Assumetheseparticularvegetariansdon’t eatfish.

SubqueriesintheWHEREclause–theALLoperator

Like“IN”,the“ALL”operatorallowsyoutocomparealistofvaluestoasinglevalue. However,itallowsyoutouseoperatorslike“>”todoso. Theexamplebelowshowshow.

SELECT*

FROMProducts

WHEREUnitPrice>=ALL

(

 

SELECTUnitPrice

FROMProducts

)

Thesubqueryreturnsalistofunitprices. Themainqueryreturnsalistofproductswitha unitpriceequaltoorgreaterthaneachvalueonthelisti.e.equaltothehighestvalueon thelist. Thisgivesyoutherecordforthemostexpensiveproduct.

Atthispoint,youmightthinkthatyoucouldjustuseanaggregatefunctionwithouta subquery,andgetthemaximumunitprice. Youcould,butyoucouldn’tgettherestofthe productrecordthatway(tryitandsee). Youcoulduseanaggregatefunctioninsidethe “WHERE”clause,asbelow:

WHEREUnitPrice=

(

 

SELECTMax(UnitPrice)

FROMProducts

)

However,thisisnosimpler:youstillhavetouseasubquery.

Exercise–19.6

(answer)

Inthechapterongroupingandaggregatefunctions,wementionedthisexactproblem:that youcangetanaggregatevalue,suchasaminimumormaximum,butnottherecord(s) associatedwithit(inthatcase,therecordforthecheapestproduct). Thequeriesabove showhowtosolvethis. Canyoualterthe“ALL”querytoreturntherecordforthe cheapestproduct?

SubqueriesintheWHEREclause-the“ANY”operator

Thisiswrittenintothequerythesamewayas“ALL”,exceptthatitreturnstrueifeven oneofthevaluesinalistmeetsthespecifiedcondition. Runthequerybelowtosee.

SELECT*

FROMProducts

WHEREUnitPrice<ANY

(

 

SELECTUnitPrice

FROMProducts

)

Thisqueryreturnsalltherowsofthetable,apartfromtheoneforthemostexpensive product. Themostexpensiveproductdoesn’thaveaunitpricecheaperthananyofthe otherproducts,soitnevermeetsthecondition.

Wheretogofromhere

ThereisalotmoretoSQL. Youcanuseittochangethedatainadatabase. Youcanuse ittomakeyourowntablesandfunctionsortomodifyotherpeople’s. Itisnotjustaway ofgettingdata,buttheactuallanguageusedforcontrollinghowdatabaseswork.

MostpeoplewilluseSQLonlytogetdataforreportsoranalysis. Ifthatdescribesyou, andyouoftenfindyourselfexporting,orjustcopy-and-pasting,theresultsofyourSQL queriesintoExcelforfurtherwork,youmaywishtomoveontoasimilarcourseIwrote calledExcel:LearnFormulasFast. It’saconcise,exercise-packedtourofwhatExcelcan dowithdata,whichismuchmorethanjustcalculations. It’savailableine-bookformat.

Otherpeoplewillgoontododatabaseadministrationanddevelopment. Thismayinvolve importingnewrecords,correctingfaultyrecordsinbulk,changingthedatabasestructure itself,and,ofcourse,designingnewqueriesforallthereportsthatusersneed. Ifthat’s somethingyou’dbeinterestedin,thatcanalsoallbepractisedusingtheSQLServerand theNorthwinddatabase.

Ifyouareinterestedindatabasedesign,ratherthanjustworkingwithdatainside databases,thisisaseparatetopictoSQL. YoucanuseSSMStocreateaSQLServer database,butit’sworthreadingupondatabasedesigntopicslikenormalisationfirst. If youwanttogiveaSQLServerdatabaseauserinterface,e.g.data-entryforms,youwill needtouseseparatesoftwaretodesignone. Forexample,MicrosoftVisualStudioallows youtodesignwebsites,soyoucouldusethattomakeonethataccessesyourdatabase. If youwanttogodownthenon-Microsoftrouteforyourwebsite,youcouldusePHPand MySQLinstead,whicharealsofreetodownloadonline.

Ifyou’renotintowebdesign,andjustwanttogetstartedexperimentingwithdatabases, youcoulduseMicrosoftAccess. It’slimited,comparedtotheoptionsabove,butalotof computershaveitalreadyinstalled,anditletsyoudesignformsandreportswithout havingtouseothersoftwareorlearningaboutwebdesignorprogramming,soitmaygive youaquickwaytotrysomethingsout.

Author’snote

Ihopeyoufoundthisbookuseful. Ifso,youmaywishtotrysomeofmyotherbooks, listedoverthepage.

Ialsohopethatthisbooksavedyoutime,thatitprovidedclear,conciseinformation,anda simplewaytopractiseusingit. That’sthestandardIaimfor:towritethekindofbook thatIwouldwanttouse.

Atthispoint,Iwouldnormallyasknicelyforareviewonthebook’sAmazonpage. However,fromleavingreviewsmyself,Iknowitcanbehardtothinkwhattowrite,so I’mtryingoutwaystomakeiteasier. Instead,I’masking,ifyoucanspareacoupleof minutes,please,gotothisbook’sAmazonpage,click“leaveareview”,andtypeinany oneofthereviewsbelowthatyouagreewith:

Thisbookdideverythingitsaiditwould.

Thisbookwasclearandtothepoint.

Ifoundthepracticeexerciseshelpful.

IdidlearnSQLfast!

Ilikethewaythisbookiswritten.

ThisbookwaswellformattedforKindle.

Idoappreciatehonestreviews. Leavingagoodreviewhelpsmybooksdowelland encouragesmetowritemoreofthem. Oneofthosebooksmaythenbetheretosaveyou timewhenyounextneedtolearnanewskillinahurry. That’swhatIcanoffer,honestly, inreturnforthesupportofagoodreview.

Finally,ifyoufeelthatanythingaboutthisbookfallsshortofwhatyouhopedfor,youcan

letmeknowat:

Toskipovertheanswersection,andseeotherbooksIhavewritten,follow

thelinkbelow:

Otherbooksyoumayfinduseful

Answers

Answer–1.1

(back)

SELECT*

FROMCategories

Answer–1.2

(back)

SELECTProductName,UnitPrice,UnitsInStock

FROMProducts

Answer–2.1

(back)

SELECTProductNameASProduct,UnitPrice,UnitsInStock,UnitPrice*UnitsInStock

ASStockValue

FROMProducts

Answer–2.2

(back)

SELECTProductName,UnitPrice*UnitsOnOrder

FROMProducts

Answer–2.3

(back)

SELECTProductName,UnitsInStock+UnitsOnOrder

FROMProducts

Answer–2.4

(back)

SELECTUnitPrice/5

FROMProducts

Answer–2.5

(back)

SELECT7*8

Answer–2.6

(back)

SELECTProductName,UnitsInStock%12

FROMProducts

Answer–2.7

(back)

SELECTProductName,(UnitsInStock+UnitsOnOrder)*UnitPrice

FROMProducts

Answer–2.8

(back)

SELECTContactName+‘,‘+Address+‘,‘+City

FROMCustomers

Answer–2.9

(back)

SELECTContactName+‘,‘+Address+‘,‘+CityAS‘NameandAddress’

FROMCustomers

Answer–2.10

(back)

SELECTOrderID,ShipCity+‘,‘+IsNull(ShipRegion,”)+‘,‘+ShipCountryAS‘Order

Address’

FROMOrders

Answer–2.11

(back)

SELECTOrderID,ShipCity+‘,‘+IsNull(ShipRegion+‘,‘,”)+ShipCountryAS‘Order

Address’

FROMOrders

ThisanswerdoesbecomealittlehardtoreadwithinthebracketsoftheIsNullfunction. However,allwehavedoneistomovethe“commaplusspace”intothefirstargumentof thefunctionontotheendoftheShipRegionfield. Ifthisfieldisnull,thenaddingthe stringconstantwon’taffectit:itwillstillbenull. Sothistime,thesecond“commaplus space”willonlyaddedtotheaddressiftheShipRegionisnotnull.

Answer–2.12

(back)

SELECTOrderID,ShipCity+‘,‘+ShipRegion+‘,‘+ShipCountryAS‘OrderAddress’

FROMOrders

Thisquerynowreturnsnullvaluesfororderaddresswhenevertheregionisnull.

Answer–3.1

(back)

SELECT*

FROMCustomers

WHERECity=‘Berlin’

Answer–3.2

(back)

SELECTContactName,Phone

FROMCustomers

WHERECity=‘Berlin’

Answer–3.3

(back)

SELECTCity

FROMSuppliers

WHERECountry=‘Japan’

Answer–3.4

(back)

SELECTCity

FROMSuppliers

WHERECountry=‘India’

Thisqueryreturnsnorows. Thisisthecorrectresult. Youdon’thaveanysuppliersbased inIndia,sotheWHEREclauseremovesalltherows.

Theoppositecasehereisthat,ifyouhadseveralsuppliersbasedinthesamecityinIndia, thatcity’snamewouldappearseveraltimesinyourresults. Thetablerecordsareoneper supplier,notonepercity,sothisquerycanreturnduplicaterows. We’llcoverhowto preventsuchduplicationinthechapteronthe“DISTINCT”keyword,lateron.

Answer–3.5

(back)

SELECTProductName,UnitsInStock FROMProducts

WHEREUnitsInStock>=10

Answer–3.6

(back)

SELECTProductName,UnitPrice FROMProducts

WHEREUnitPrice>21.35

Answer–3.7

(back)

SELECT* FROMProducts

WHEREUnitsInStock*UnitsOnOrder<100

Answer–3.8

(back)

SELECTProductName

FROMProducts

WHEREProductNameLIKE‘P%’

Answer–3.9

(back)

SELECT* FROMEmployees

WHEREHireDate>=‘1993-01-01’

Answer–4.1

(back)

SELECTProductName,UnitsInStock FROMProducts

WHEREUnitsInStock>=10

ANDUnitsInStock<20

Answer–4.2

(back)

SELECT* FROMOrders

WHEREOrderDate>=‘1997-01-01’

ANDShipCountry=‘Brazil’

Answer–4.3

(back)

SELECT* FROMOrders

WHEREOrderDate>=‘1997-01-01’

ANDOrderDate<‘1998-01-01’

ANDShipCountry=‘Brazil’

Answer–4.4

(back)

SELECT*

FROMEmployees

WHERECountry=‘UK’

ORCity=‘Seattle’

Answer–4.5

(back)

SELECT*

FROMCustomers

WHERECountry<>‘USA’

Answer–4.6

(back)

SELECT*

FROMCustomers

WHEREContactTitleLIKE‘Sales%’

ORContactTitleLIKE‘Marketing%’

Answer–4.7

(back)

SELECTContactName,Phone,ContactTitle,Country

FROMCustomers

WHERECountry<>‘USA’

AND(ContactTitleLIKE‘Sales%’

ORContactTitleLIKE‘Marketing%’)

Answer–4.8

(back)

SELECTContactName,Phone,ContactTitle,Country

FROMCustomers

WHERECountry<>‘USA’

ANDNOT(ContactTitleLIKE‘Sales%’

ORContactTitleLIKE‘Marketing%’)

Answer–4.9

(back)

SELECTContactName,Phone,ContactTitle,Country

FROMCustomers

WHERE(Country<>‘USA’

ANDCountry<>‘Mexico’)

ANDNOT(ContactTitleLIKE‘Sales%’

ORContactTitleLIKE‘Marketing%’)

Thereareseveralqueriesyoucouldusetogetthisdata. Theonebelowavoidsusing brackets.

SELECTContactName,Phone,ContactTitle,Country

FROMCustomers

WHERECountry<>‘USA’

ANDCountry<>‘Mexico’

ANDContactTitleNOTLIKE‘Sales%’

ANDContactTitleNOTLIKE‘Marketing%’

Answer–5.1

(back)

SELECTDISTINCTCountry

FROMSuppliers

Answer–6.1

(back)

SELECTProductName,CategoryID,UnitPrice

FROMProducts

ORDERBYCategoryID,UnitPrice

Asascendingorderisthedefault,thereisnoneedtouseanykeywordswithUnitPriceor (CategoryID). Thereisan“ASC”keywordinSQL,theoppositeof“DESC”,butwedon’t needit.

Answer–7.1

(back)

SELECTTOP10ProductName,UnitPrice

FROMProducts

ORDERBYUnitPrice

Answer–8.1

(back)

SELECTSum(UnitsInStock)

FROMProducts

WHEREDiscontinued=1

Answer–8.2

(back)

SELECTSum(UnitsInStock)

FROMProducts

WHERECategoryID=1

Answer–8.3

(back)

SELECTSupplierID,Sum(UnitsOnOrder)

FROMProducts

GROUPBYSupplierID

Answer–8.4

(back)

SELECTSupplierID,Sum(UnitsOnOrder*UnitPrice)

FROMProducts

GROUPBYSupplierID

Answer–8.5

(back)

SELECTCategoryID,Max(UnitPrice)

FROMProducts

GROUPBYCategoryID

Hopefully,ifyoudidn’tnoticeitalready,thisexercisemadeyounoticetheneedtochange thegroupingfieldintwoplaces:theSELECTandGROUPBYclauses. Typically,when groupingisused,thenon-aggregatefieldsintheseclausesshouldmatch.

Answer–8.6

(back)

SELECTSupplierID,Min(UnitPrice)

FROMProducts

GROUPBYSupplierID

Answer–9.1

(back)

SELECTCategoryID,Sum(UnitsInStock)

FROMProducts

GROUPBYCategoryID

HAVINGSum(UnitsInStock)>100

Answer–9.2

(back)

SELECTSupplierID,Count(*)

FROMProducts

GROUPBYSupplierID

HAVINGCount(*)=1

Answer–9.3

(back)

SELECTCategoryID,Sum(UnitsOnOrder) FROMProducts GROUPBYCategoryID

HAVINGSum(UnitsOnOrder)=0

Answer–9.4

(back)

SELECTOrderID,Sum(Quantity) FROM[OrderDetails] GROUPBYOrderID

HAVINGSum(Quantity)<50

Answer–9.5

(back)

SELECTOrderID,Max(Discount) FROM[OrderDetails] GROUPBYOrderID

HAVINGMax(Discount)>0.2

Answer–9.6

(back)

SELECTOrderID,Sum(Quantity*UnitPrice)AsCashValue,Sum(Quantity)AsUnits

FROM[OrderDetails]

GROUPBYOrderID

Answer–11.1

(back)

SELECTc.CategoryName,p.*

FROMProductsp

INNERJOINCategoriesc

ONp.CategoryID=c.CategoryID

Answer–11.2

(back)

SELECTc.CompanyName

FROMOrderso

INNERJOINCustomersc

ONo.CustomerID=c.CustomerID

Answer–11.3

(back)

SELECTs.CompanyName,Sum(p.UnitsOnOrder)

FROMProductsp

INNERJOINSupplierss

ONp.SupplierID=s.SupplierID

GROUPBYs.CompanyName

Answer–11.4

(back)

SELECTc.CategoryName,Max(p.UnitPrice)

FROMProductsp

INNERJOINCategoriesc

ONp.CategoryID=c.CategoryID

GROUPBYCategoryName

Answer–12.1

(back)

SELECTDISTINCTCompanyName

FROMCustomersc

INNERJOINOrderso

ONc.CustomerId=o.CustomerId

Answer–12.2

(back)

SELECT*

FROMTerritoriest

LEFTJOINEmployeeTerritoriese

ONt.TerritoryID=e.TerritoryID

Answer–12.3

(back)

SELECT*

FROMTerritoriest

LEFTJOINEmployeeTerritoriese

ONt.TerritoryID=e.TerritoryID

WHEREe.EmployeeIDIsNull

Answer–12.4

(back)

SELECT*

FROMTerritoriest

INNERJOINEmployeeTerritoriese

ONe.TerritoryID=t.TerritoryID

Yes,youcouldkeepusingthequeryfromthelastexercise,withitsleftouterjoin,andjust changetheconditioninthe“WHERE”clause,butthiswouldbeinefficient. Ifyou queriedalargetablethisway,itwouldslowyourquery. Thisdoesn’tmatterhere,but speedisanissueinbiggerdatabases.

Answer–12.5

(back)

SELECTFirstName,LastName,TerritoryDescription

FROMEmployeese

INNERJOINEmployeeTerritorieset

ONe.EmployeeID=et.EmployeeID

INNERJOINTerritoriest

ONet.TerritoryID=t.TerritoryID

Thisshouldgiveyouthesamenumberofresultsasbefore(49). Youmayhavedonethe joininadifferentorder,butthisdoesn’tmatterforinnerjoins.

Answer–13.1

(back)

SELECTstaff.FirstName+‘‘+staff.LastNameASStaff,

boss.FirstName+‘‘+boss.LastNameAsBoss

FROMEmployeesstaff

LEFTOUTERJOINEmployeesboss

ONstaff.ReportsTo=boss.EmployeeID

Answer–14.1

(back)

SELECT(

SELECTCount(*)

FROMShippers

)*(

SELECTCount(*)

FROMCustomers

)

Answer–14.2

(back)

Thequickway:

SELECT*

FROMShippers,Customers

The“join”way:

SELECT* FROMShippers INNERJOINCustomers

ON1=1

Answer–14.3

(back)

Thequickway:

SELECTCount(*)

FROMShippers,Customers

The“join”way:

SELECTCount(*)

FROMShippers

INNERJOINCustomers

ON1=1

Answer–15.1

(back)

SELECTCompanyName,‘Supplier’ASCompanyType,City,Country

FROMSuppliers

UNIONALL

SELECTCompanyName,‘Customer’,City,Country

FROMCustomers

Answer–18.1

(back)

SELECTName

FROMSys.Views

WHERENameLIKE‘%Product%’

Answer–19.1

(back)

SELECTSum(StockValue)

FROM(

SELECTProductName,UnitsInStock*UnitPriceASStockValue

FROMProducts

)sq

Answer–19.2

(back)

SELECT*

FROM

(

SELECTCompanyName,‘Supplier’ASCompanyType,City,Country

FROMSuppliers

UNIONALL

SELECTCompanyName,‘Customer’,City,Country

FROMCustomers

)sq

ORDERBYsq.Country,sq.City

Answer–19.3

(back)

SELECT*

FROMProducts

WHERESupplierIDIN

(

 

SELECTSupplierID

FROMSuppliers

WHERECountryIN(‘UK’,‘USA’)

)

Answer–19.4

(back)

SELECT*

FROMProducts

WHERECategoryIDIN

(

 

SELECTCategoryID

FROMCategories

WHERECategoryName=‘Seafood’

)

Inthiscase,youcouldalsouse“=”insteadof“IN”,asthereisonlyoneseafoodcategory,

andthereforeonlyoneIDreturnedbythesubquery.

Answer–19.5

(back)

SELECT*

FROMProducts

WHERECategoryIDIN

SELECTCategoryID

FROMCategories

WHERECategoryNameNOTIN(‘Seafood’,‘Meat/Poultry’)

)

Answer–19.6

(back)

SELECT*

FROMProducts

WHEREUnitPrice<=ALL

(

 

SELECTUnitPrice

FROMProducts

)

Otherbooksyoumayfinduseful

IhavewrittensimilarLearn…Fastcoursesfor:

CommandLineandBatchScript(forWindows)

ExcelVBA(functiondesign)

Excel(formulas)

Ihavealsowrittenbriefguidesto:

Keyboardshortcuts

ITSupport

Alloftheaboveareavailablease-books.