Selasa, 15 Maret 2016

LIMIT di SQL Server


For details on the ROW_NUMBER() function and its use, see: http://msdn2.microsoft.com/en-us/library/ms186734.aspx
For info on other ranking functions in SQL Server 2005, see: http://msdn2.microsoft.com/en-us/library/ms189798.aspx

source : http://blogs.msdn.com/b/sqlserver/archive/2006/10/25/limit-in-sql-server.aspx

Senin, 14 Maret 2016

IF ELSE

Local Variables

As with any programming language, T-SQL allows you to define and set variables. A variable holds a single piece of information, similar to a number or a character string. Variables can be used for a number of things. Here is a list of a few common variable uses:
  • To pass parameters to stored procedures, or function
  • To control the processing of a loop
  • To test for a true or false condition in an IF statement
  • To programmatically control conditions in a WHERE statement
In SQL Server a variable is typical known as a local variable, due the scope of the variable. The scope of a local variable is only available in the batch, stored procedure or code block in which it is defined. A local variable is defined using the T-SQL "DECLARE" statement. The name of the local variable needs to start with a "@" sign as the first character of its name. A local variable can be declared as any system or user defined data type. Here is a typical declaration for an integer variable named @CNT:

 DECLARE @CNT INT
 
More than one variable can be defined with a single DECLARE statement. To define multiple variables, with a single DECLARE statement, you separate each variable definition with a comma, like so:

 DECLARE @CNT INT, @X INT, @Y INT, @Z CHAR(10)
 
Above I have defined 4 local variables with a single DECLARE statement. A local variable is initially assigned a NULL value. A value can be assigned to a local variable by using the SET or SELECT statement. On the SET command you specify the local variable and the value you wish to assign to the local variable. Here is an example of where I have defined my @CNT variable and then initialize the variable to 1.

 DECLARE @CNT INT
 SET @CNT = 1
 
Here is an example of how to use the SELECT statement to set the value of a local variable.

 DECLARE @ROWCNT int
 SELECT @ROWCNT=COUNT(*) FROM pubs.dbo.authors
 
The above example sets the variable @ROWCNT to the number of rows in the pubs.dbo.authors table.
One of the uses of a variable is to programmatically control the records returned from a SELECT statement. You do this by using a variable in the WHERE clause. Here is an example that returns all the Customers records in the Northwind database where the Customers Country column is equal to 'Germany'

 Declare @Country varchar(25) 
 set @Country = 'Germany'
 select CompanyName from Northwind.dbo.Customers
 where Country = @Country

IF ... ELSE

T-SQL has the "IF" statement to help with allowing different code to be executed based on the results of a condition. The "IF" statement allows a T-SQL programmer to selectively execute a single line or block of code based upon a Boolean condition. There are two formats for the "IF" statement, both are shown below:

Format one: IF <condition> <then code to be executed when condition true>
Format two: IF <condition> <then code to be executed when condition true>                     ELSE < else code to be executed when condition is false>

In both of these formats, the <condition> is a Boolean expression or series of Boolean expressions that evaluate to true or false. If the condition evaluates to true, then the "then code" is executed. For format two, if the condition is false, then the "else code" is executed. If there is a false condition when using format one, then the next line following the IF statement is executed, since no else condition exists. The code to be executed can be a single TSQL statement or a block of code. If a block of code is used then it will need to be enclosed in a BEGIN and END statement.

Let's review how "Format one" works. This first example will show how the IF statement would look to execute a single statement, if the condition is true. Here I will test whether a variable is set to a specific value. If the variable is set to a specific value, then I print out the appropriate message.

 Declare @x int
 set @x = 29
 if @x = 29 print 'The number is 29'
 if @x = 30 print 'The number is 30'
 
The above code prints out only the phrase "The number is 29", because the first IF statement evaluates to true. Since the second IF is false the second print statement is not executed.
Now the condition statement can also contain a SELECT statement. The SELECT statement will need to return value or set of values that can be tested. If a SELECT statement is used the statement needs to be enclosed in parentheses.

 if (select count(*) from Pubs.dbo.Authors
         where au_lname like '[A-D]%') > 0 
    print 'Found A-D Authors'
 
Here I printed the message "Found A-D Authors" if the SELECT statement found any authors in the pubs.dbo.authors table that had a last name that started with an A, B, C, or D.
So far my two examples only showed how to execute a single T-SQL statement if the condition is true. T-SQL allows you to execute a block of code as well. A code block is created by using a "BEGIN" statement before the first line of code in the code block, and an "END" statement after that last line of code in the code block. Here is any example that executes a code block when the IF statement condition evaluates to true.

 if db_name() = 'master' 
   begin
     Print 'We are in the Master Database'
     Print ''
     Print 'So be careful what you execute'
   End
 
Above a series of "PRINT" statements will be executed if this IF statement is run in the context of the master database. If the context is some other database then the print statements are not executed.
Sometimes you want to not only execute some code when you have a true condition, but also want to execute a different set of T-SQL statements when you have a false condition. If this is your requirement then you will need to use the IF...ELSE construct, that I called format two above. With this format, if the condition is true then the statement or block of code following the IF clause is executed, but if the condition evaluates to false then the statement or block of code following the ELSE clause will be executed. Let's go through a couple of examples.
For the first example let's say you need to determine whether to update or add a record to the Customers table in the Northwind database. The decision is based on whether the customer exists in the Northwind.dbo.Customers table. Here is the T-SQL code to perform this existence test for two different CustomerId's.

 if exists(select * from Northwind.dbo.Customers 
             where CustomerId = 'ALFKI')
     Print 'Need to update Customer Record ALFKI'
 else
     Print 'Need to add Customer Record ALFKI'
 
 if exists(select * from Northwind.dbo.Customers 
             where CustomerId = 'LARSE')
     Print 'Need to update Customer Record LARSE'
 else
     Print 'Need to add Customer Record LARSE'
 
The first IF...ELSE logic checks to see it CustomerId 'ALFKI' exists. If it exists it prints the message "Need to update Customer Record", if it doesn't exist the "Need to add Customer Record" is displayed. This logic is repeated for CustomerId = 'LARS'. When I run this code against my Northwind database I get the following output.

 Need to update Customer Record ALFKI
 Need to add Customer Record LARSE
 
As you can see from the results CustomerId 'ALFKI' existed, because the first print statement following the first IF statement was executed. Where as in the second IF statement CustomerId 'LARSE' was not found because the ELSE portion of the IF...ELSE statement was executed.
If you have complicated logic that needs to be performed prior to determining what T-SQL statements to execute you can either use multiple conditions on a single IF statement, or nest your IF statements. Here is a script that determines if the scope of the query is in the 'Northwind' database and if the "Customers" table exists. I have written this query two different ways, one with multiple conditions on a single IF statement, and the other by having nested IF statements.

 -- Single IF Statement with multiple conditions
 use Northwind
 if db_name() = 'Northwind' and 
    (select count(*) from sysobjects   
       where name = 'Customers') = 1
   print 'Table Customers Exist'
 else 
   print 'Not in the Northwind database' + 
         ' or Table Customer does not exist'
 
 -- Nested IF Statements
 use Northwind
 if db_name() = 'Northwind' 
    if (select count(*) from sysobjects 
          where name = 'Customers') = 1
      print 'Table Customers Exist'
    else
      print 'Table Customer does not exist'
 else 
   print 'Not in the Northwind Database'
 
As you can see I tested to see if the query was being run from the Northwind database and whether the "Customers" table can be found in sysobjects. If this was true, I printed the message "Table Customers Exists". In the first example I had multiple conditions in a single IF statement. Since I was not able to determine which parts of the conditions in the IF statement where false the ELSE portion printed the message "Not in Northwind database or Table Customer does not exist". Now in the second example where I had a nested IF statement I was able to determine whether I was in the wrong database or the object "Customers" did not exist. This allowed me to have two separate print statements to reflect exactly what condition was getting a false value.

Conclusion

I hope that this article has helped you understand how to declare and use local variables, as well as IF...ELSE logic. Local variables are useful to hold the pieces of information related to your programming process. Where as the IF statement helps control the flow of your program so different sections of code can be executed depending on a particular set of conditions. As you can see nesting IF statements and/or having multiple conditions on an IF statement allows you to further refine your logic flow to meet your programming requirements. My next article in this T-SQL programming series will discuss how to build a programming loop.

source : http://www.databasejournal.com/features/mssql/article.php/3087431/T-SQL-Programming-Part-1---Defining-Variables-and-IFELSE-logic.htm

Cursor

Using a Cursor

The first method I will discuss uses a cursor to process through a set of records one record at a time. A cursor is basically a set of rows that you define based on a record set returned from a query. A cursor allows applications a mechanism to process through a result set one row at a time. With a cursor an application is allowed to position itself to a specific row, scroll back and forth, and a number of other things. It would take a series of articles to describe all the functionality of a cursor. For the purpose of this article I'm only going to focus on how to use the default scrolling functionality of a cursor. This default functionality will only read from the first row to the last row in a cursor, one row at a time. I will leave additional cursor topics to another article series.
To define a cursor the DECLARE CURSOR statement is used. Here is the basic format for the simple cursor topic I will be discussing in this article.

DECLARE cursor_name CURSOR 
 FOR select_statement

The cursor_name is the name you want to associate with the cursor. The select_statement is the query that will determine the rows that make up the cursor. Note there are other parameters/options associated with the DECLARE CURSOR statement that help define more complicated cursor processing than I will be covering in this article. For these additional options please read Microsoft SQL Server Books Online.
Let's review a fairly simple cursor example. This example will define a cursor that contains the top 5 Customer_Id's in the Customer table in the Northwind database. It will then process through each record displaying a row number and the CustomerID for each. Here is the code to do this.

 declare @CustId nchar(5)
 declare @RowNum int
 declare CustList cursor for
 select top 5 CustomerID from Northwind.dbo.Customers
 OPEN CustList
 FETCH NEXT FROM CustList 
 INTO @CustId
 set @RowNum = 0 
 WHILE @@FETCH_STATUS = 0
 BEGIN
   set @RowNum = @RowNum + 1
   print cast(@RowNum as char(1)) + ' ' + @CustId
   FETCH NEXT FROM CustList 
     INTO @CustId
 END
 CLOSE CustList
 DEALLOCATE CustList

Here are the results that are generated from the print statement when I run it against my Northwind Database.

 1 ALFKI
 2 ANATR
 3 ANTON
 4 AROUT
 5 BERGS

Let's look at the above code in a little more detail. I first declared a cursor called "CustList". The "CustList" cursor is populated using a SELECT statement that uses the TOP clause to return only the top 5 CustomerId's. Next the cursor is opened. Each record in the "CustList" cursor is retrieved, one record at a time, using the "FETCH NEXT" next statement. The "FETCH NEXT" statement populates the local variable @CustID with the CustomerID of the current record being fetched. The @@FETCH_STATUS variable controls whether the WHILE loop is executed. @@FETCH_STATUS is set to zero when a record is successfully retrieved from the cursor "CustList". Inside the WHILE loop the @RowNum variable is incremented by 1 for each record processed. The calculated Row Number and @CustId are then printed out. Lastly, a "FETCH NEXT" statement is used to retrieve the next row before the next cycle of the WHILE loop. This process continues one record at a time until all records in cursor "CustList" have been processed.

Using a Select Statement

You can also use a SELECT statement to process through a set of records one record at a time. To do this I will issue an initial SELECT statement that will return the first row, then a series of follow on SELECT statements where each SELECT statement retrieves the next row. This is done by using the "TOP 1" clause of the SELECT statement, and a WHERE statement.
I will use the same example as above and only return the top 5 CustomerID's from the Northwind database Customers table. In this code I will use two different "SELECT TOP 1" statements and a WHILE loop to return all 5 records. Each record will be processed one at a time.

 declare @CustId nchar(5)
 declare @RowNum int
 select top 1 @CustId=CustomerID from Northwind.dbo.Customers
 set @RowNum = 0 
 WHILE @RowNum < 5
 BEGIN
   set @RowNum = @RowNum + 1
   print cast(@RowNum as char(1)) + ' ' + @CustId
   select top 1 @CustId=CustomerID from Northwind.dbo.Customers
                where CustomerId > @CustID
 END
 
Here you can see the first SELECT statement selects only the first CustomerID. This ID is placed in the local variable @CustID. The WHILE loop is controled by the local variable @RowNum. Each time through the WHILE loop, the Row Number and CustomerID are printed out. Prior to returning to the top of the WHILE loop I used another "SELECT TOP 1" statement to select the next CustomerID. This SELECT statement uses a WHERE clause on the SELECT statement to select the first CustomerID that is greater than the CustomerID that was just printed. The WHILE loop is process 5 times, allowing the SELECT TOP 1 method to retrieve the top 5 CustomerID's one records at a time. This example produces the same printed output as my prior CURSOR example.

Conclusion

Hopefully this article has given you some ideas on how to use a CURSOR, and a SELECT statement to process through a set of records. I use both of these methods, although I find using a SELECT statement to be a little simpler to code. You will need to decide which solution makes the most sense in your environment.

source : http://www.databasejournal.com/features/mssql/article.php/3111031/T-SQL-Programming-Part-3---Processing-Sequentially-Through-a-Set-of-Records.htm

sp_executesql

The sp_executesql SP is a system SP provided by Microsoft. This SP can be found in the master database. Here is the calling syntax for this SP:

sp_executesql [@stmt =] stmt
[ 
    {, [@params =] N'@parameter_name  data_type [,...n]' } 
    {, [@param1 =] 'value1' [,...n] }
]
 
Where [@stmt =] stmt is the dynamic T-SQL statement that you would like to execute, [@params =] N'@parameter_name  data_type [,...n]' is used to identify the list of variables and the data type for each dynamic variable that is contained in the dynamic T-SQL statement, and [@param1 =] 'value1' [,...n] is used to provide values for each variable used in the dynamic T-SQL statement being executed. More information about this stored procedure, and how to use it can be found in Microsoft SQL Server Books Online.
In order to show you how to return variables from the sp_executesql SP to your calling T-SQL, I will show you a real simple example. My example will return the numbers of records in a table that meet a specific WHERE criteria that is pass dynamically to the sp_executesql SP. Here is the code:

use Northwind
go
declare @RECCNT int
declare @ORDID varchar(10)
declare @CMD Nvarchar(100)
set @ORDID = 10436
SET @CMD = 'SELECT @RECORDCNT=count(*) from [Orders]' + 
           ' where OrderId < @ORDERID'
print @CMD
exec sp_executesql @CMD,
                   N'@RECORDCNT int out, @ORDERID int', 
                   @RECCNT out,
                   @ORDID  
print 'The number of records that have an OrderId' +  
      ' greater than ' + @ORDID + ' is ' + 
      cast(@RECCNT as char(5))
 
In this example you can see that the table from which I am returning the record count is the "Orders" table in the "Northwind" database. To make this code dynamic, the WHERE statement criteria is built on the fly by using a value passed in to the sp_executesql SP call which will set the @ORDERID variable in the dynamic T-SQL string. The record count for the number of Orders records that have an OrderId less than the @ORDERID variable value will be returned in a variable named @RECORDCNT. Both these local variables are specified in the dynamic T-SQL command, which is passed to sp_executesql SP in the string @CMD. These variables are not declared the calling T-SQL code, but instead are declared within the sp_executesql SP.

Note that the above code has a couple of PRINT statements. The first PRINT statement in the code above displays the dynamic T-SQL command to be executed by the sp_executesql SP. Here is the dynamic T-SQL code that is displayed when this first PRINT statement is executed:

SELECT @RECORDCNT=count(*) from [Orders] where OrderId < @ORDERID
 
Since this T-SQL statement contains variables, the sp_executesql (SP) requires that the calling T-SQL code identify these variables, and their format in the parameters passed to this SP. Specifying the definition of these variables is done in the second parameter of the sp_executesql call above (N'@RECORDCNT int out, @ORDERID int'). As you can see the @RECORDCNT variable is defined as output. This allows this variable to return a value from the sp_executesql to the calling T-SQL code. Defining the definitions of these variables allows the sp_executesql SP to define these variables locally within the SP code.
When variables are used in the calling program to pass and return values you also need to identify these variables to sp_executesql SP. You need to do this so that the sp_executesql SP knows which variables in the calling program are associated with the variables placed in the command string, which is passed in the first parameter (@stmt) of the sp_executesql SP. In this example, I wanted to associate the variable @RECORDCNT with the variable @RECCNT, which is defined in my calling T-SQL code, as well as associate @ORDERID with the @ORDID variable, which is also defined in my calling T-SQL code. These variable associations are done using the final parameters passed to the sp_executesql SP; in my example this would be the third and forth parameters in the sp_executesql statement in the code above. The order of the third and forth parameters, in this case, need to match the order in which these variables are defined in the second parameter of the sp_executesql call. Also important is to identify that the @RECCNT variable is output. This allows the sp_executesql statement to set the @RECCNT variable with the results of @RECORDCNT when the sp_executesql statement is processed.
The output of the above script, when run on my server, displays the following output from the final PRINT statement in the script:

The number of records that have an OrderId greater than 10436 is 188

Conclusion

Although I have shown you only a simple example, which could have easily been done a number of other ways, hopefully you see the value of how the sp_executesql SP can process dynamic T-SQL and return results to variables in the calling T-SQL code. If you already have a need for this functionality then you should be able to expand on this method to meet your needs. As you can see, it is relatively straightforward to get your dynamic T-SQL code to set variables in your calling T-SQL when using the sp_executesql SP.

source : http://www.databasejournal.com/features/mssql/article.php/3286501/T-SQL-Programming-Part-4---Setting-Variables-in-Calling-T-SQL-Code-While-Using-spexecutesql.htm

Subquery

What is a Subquery?

A subquery is a SELECT statement that is nested within another T-SQL statement. A subquery SELECT statement if executed independently of the T-SQL statement, in which it is nested, will return a result set. Meaning a subquery SELECT statement can standalone and is not depended on the statement in which it is nested. A subquery SELECT statement can return any number of values, and can be found in, the column list of a SELECT statement, a FROM, GROUP BY, HAVING, and/or ORDER BY clauses of a T-SQL statement. A Subquery can also be used as a parameter to a function call. Basically a subquery can be used anywhere an expression can be used.

Use of a Subquery in the Column List of a SELECT Statement

Suppose you would like to see the last OrderID and the OrderDate for the last order that was shipped to Paris. Along with that information, say you would also like to see the OrderDate for the last order shipped regardless of the ShipCity. In addition to this, you would also like to calculate the difference in days between the two different OrderDates. Here is my T-SQL SELECT statement to accomplish this:

select top 1 OrderId,convert(char(10),
       OrderDate,121) Last_Paris_Order,
      (select convert(char(10),max(OrderDate),121) from   
             Northwind.dbo.Orders) Last_OrderDate,
       datediff(dd,OrderDate,
      (select Max(OrderDate)from Northwind.dbo.Orders)) Day_Diff
from Northwind.dbo.Orders
where ShipCity = 'Paris'
order by OrderDate desc 
 
The above code contains two subqueries. The first subquery gets the OrderDate for the last order shipped regardless of ShipCity, and the second subquery calculates the number of days between the two different OrderDates. Here I used the first subquery to return a column value in the final result set. The second subquery was used as a parameter in a function call. This subquery passed the "max(OrderDate)" date to the DATEDIFF function.

Use of a Subquery in the WHERE clause

A subquery can be used to control the records returned from a SELECT by controlling which records pass the conditions of a WHERE clause. In this case the results of the subquery would be used on one side of a WHERE clause condition. Here is an example:

select distinct country from Northwind.dbo.Customers 
where country not in (select distinct country from Northwind.dbo.Suppliers)
 
Here I have returned a list of countries where customers live, but there is no supplier located in that country. I suppose if you where trying to provide better delivery time to customers, then you might target these countries to look for additional suppliers.
Suppose a company would like to do some targeted marketing. This targeted marketing would contact customers in the country with the fewest number of orders. It is hoped that this targeted marketing will increase the overall sales in the targeted country. Here is an example that uses a subquery to return the customer contact information for the country with the fewest number of orders:

select Country,CompanyName, ContactName, ContactTitle, Phone
from Northwind.dbo.Customers 
where country =
   (select top 1 country 
         from Northwind.dbo.Customers C 
                      join
              Northwind.dbo.Orders O
              on C.CustomerId = O.CustomerID
    group by country
    order by count(*)) 
 
Here I have written a subquery that joins the Customer and Orders Tables to determine the total number of orders for each country. The subquery uses the "TOP 1" clause to return the country with the fewest number of orders. The country with the fewest number of orders is then used in the WHERE clause to determine which Customer Information will be displayed.

Use of a Subquery in the FROM clause

The FROM clause normally identifies the tables used in the T-SQL statement. You can think of each of the tables identified in the FROM clause as a set of records. Well, a subquery is just a set of records, and therefore can be used in the FROM clause just like a table. Here is an example where a subquery is used in the FROM clause of a SELECT statement:

select au_lname, au_fname, title from 
     (select au_lname, au_fname, au_id from pubs.dbo.authors
          where state = 'CA')  as a 
                     join
     pubs.dbo.titleauthor ta on a.au_id=ta.au_id
                     join
     pubs.dbo.titles t on ta.title_id = t.title_id
 
Here I have used a subquery to select only the author record information, if the author's record has a state column equal to "CA." I have named the set returned from this subquery with a table alias of "a." I can then use this alias elsewhere in the T-SQL statement to refer to the columns from the subquery by prefixing them with an "a", as I did in the "ON" clause of the "JOIN" criteria. Sometimes using a subquery in the FROM clause reduces the size of the set that needs to be joined. Reducing the number of records that have to be joined enhances the performance of joining rows, and therefore speeds up the overall execution of a query.
Here is an example where I used a subquery in the FROM clause of an UPDATE statement:

set nocount on 
create table x(i int identity, 
               a char(1))
insert into x values ('a')
insert into x values ('b')
insert into x values ('c')
insert into x values ('d')
select * from x

update x
set a = b.a
from (select max(a) as a from x) b 
where i > 2

select * from x
drop table x
 
Here I created a table named "x," that has four rows. Then I proceeded to update the rows where "i" was greater than 2 with the max value in column "a". I used a subquery in the FROM clause of the UPDATE statement to identity the max value of column "a."

Use of a Subquery in the HAVING clause

In the following example, I used a subquery to find the number of books a publisher has published where the publisher is not located in the state of California. To accomplish this I used a subquery in a HAVING clause. Here is my code:

select pub_name, count(*) bookcnt 
from pubs.dbo.titles t
         join
     pubs.dbo.publishers p
     on t.pub_id = p.pub_id
group by pub_name
having p.pub_name in     
  (select pub_name from pubs.dbo.publishers where state <> 'CA')
 
Here my subquery returns the pub_name values for all publishers that have a state value not equal to "CA." The HAVING condition then checks to see if the pub_name is in the set returned by my subquery.

Conclusion

The subquery is a valuable concept to understand. Creative use of a subquery allows the desired results to be returned in a single T-SQL statement, and helps avoid the use of temporary tables and cursors to solve complicated selection criteria. In addition, depending on the query, a subquery might improve performance by reducing the number of records that SQL Server needs to process. In my next article, I will expand on the idea of subqueries by looking at correlated subqueries.

source : http://www.databasejournal.com/features/mssql/article.php/3464481/Using-a-Subquery-in-a-T-SQL-Statement.htm

Correlated Subquery

What is a Correlated Subquery?

A correlated subquery is a SELECT statement nested inside another T-SQL statement, which contains a reference to one or more columns in the outer query. Therefore, the correlated subquery can be said to be dependent on the outer query. This is the main difference between a correlated subquery and just a plain subquery. A plain subquery is not dependent on the outer query, can be run independently of the outer query, and will return a result set. A correlated subquery, since it is dependent on the outer query will return a syntax errors if it is run by itself.
A correlated subquery will be executed many times while processing the T-SQL statement that contains the correlated subquery. The correlated subquery will be run once for each candidate row selected by the outer query. The outer query columns, referenced in the correlated subquery, are replaced with values from the candidate row prior to each execution. Depending on the results of the execution of the correlated subquery, it will determine if the row of the outer query is returned in the final result set.

Using a Correlated Subquery in a WHERE Clause

Suppose you want a report of all "OrderID's" where the customer did not purchase more than 10% of the average quantity sold for a given product. This way you could review these orders, and possibly contact the customers, to help determine if there was a reason for the low quantity order. A correlated subquery in a WHERE clause can help you produce this report. Here is a SELECT statement that produces the desired list of "OrderID's":

select distinct OrderId
  from Northwind.dbo.[Order Details] OD
  where 
    Quantity <l (select avg(Quantity) * .1 
                      from Northwind.dbo.[Order Details] 
                      where OD.ProductID = ProductID)
 
The correlated subquery in the above command is contained within the parenthesis following the greater than sign in the WHERE clause above. Here you can see this correlated subquery contains a reference to "OD.ProductID". This reference compares the outer query's "ProductID" with the inner query's "ProductID". When this query is executed, the SQL engine will execute the inner query, the correlated subquery, for each "[Order Details]" record. This inner query will calculate the average "Quantity" for the particular "ProductID" for the candidate row being processed in the outer query. This correlated subquery determines if the inner query returns a value that meets the condition of the WHERE clause. If it does, the row identified by the outer query is placed in the record set that will be returned from the complete T-SQL SELECT statement.
The code below is another example that uses a correlated subquery in the WHERE clause to display the top two customers, based on the dollar amount associated with their orders, per region. You might want to perform a query like this so you can reward these customers, since they buy the most per region.

select CompanyName, ContactName, Address,
       City, Country, PostalCode from Northwind.dbo.Customers OuterC
where CustomerID in ( 
select top 2 InnerC.CustomerId
     from Northwind.dbo.[Order Details] OD join Northwind.dbo.Orders O
               on OD.OrderId = O.OrderID
          join Northwind.dbo.Customers InnerC
               on O.CustomerID = InnerC.CustomerId
     Where Region = OuterC.Region
     group by Region, InnerC.CustomerId
     order by sum(UnitPrice * Quantity * (1-Discount)) desc
     ) 
order by Region
Here you can see the inner query is a correlated subquery because it references "OuterC", which is the table alias for the "Northwind.DBO.Customer" table in the outer query. This inner query uses the "Region" value to calculate the top two customers for the region associated with the row being processed from the outer query. If the "CustomerID" of the outer query is one of the top two customers, then the record is placed in the record set to be returned.

Correlated Subquery in the HAVING Clause

Say your organizations wants to run a yearlong incentive program to increase revenue. Therefore, they advertise to your customers that if each order they place, during the year, is over $750 you will provide them a rebate at the end of the year at the rate of $75 per order they place. Below is an example of how to calculate the rebate amount. This example uses a correlated subquery in the HAVING clause to identify the customers that qualify to receive the rebate. Here is my code for this query:
select C.CustomerID, Count(*)*75 Rebate
  from Northwind.DBO.Customers C
         join
       Northwind.DBO.Orders O
         on c.CustomerID = O.CustomerID
  where Datepart(yy,OrderDate) = '1998'
  group by C.CustomerId
  having 750 < ALL(select sum(UnitPrice * Quantity * (1-Discount)) 
           from Northwind.DBO.Orders O
                  join
                Northwind.DBO.[Order Details] OD
                  on O.OrderID = OD.OrderID
           where CustomerID = C.CustomerId 
             and Datepart(yy,OrderDate) = '1998'
           group by O.OrderId
            ) 
 
By reviewing this query, you can see I am using a correlated query in the HAVING clause to calculate the total order amount for each customer order. I use the "CustomerID" from the outer query and the year of the order "Datepart(yy,OrderDate)", to help identify the Order records associated with each customer, that were placed the year '1998'. For these associated records I am calculating the total order amount, for each order, by summing up all the "[Order Details]" records, using the following formula: sum(UnitPrice * Quantity * (1-Discount)). If each and every order for a customer, for year 1998 has a total dollar amount greater than 750, I then calculate the Rebate amount in the outer query using this formula "Count(*)*75 ".
SQL Server's query engine will only execute the inner correlated subquery in the HAVING clause for those customer records identified in the outer query, or basically only those customer that placed orders in "1998".

Performing an Update Statement Using a Correlated Subquery

A correlated subquery can even be used in an update statement. Here is an example:
create table A(A int, S int)
create table B(A int, B int)

set nocount on 
insert into A(A) values(1)
insert into A(A) values(2)
insert into A(A) values(3)
insert into B values(1,1)
insert into B values(2,1)
insert into B values(2,1)
insert into B values(3,1)
insert into B values(3,1)
insert into B values(3,1)

update A 
  set S = (select sum(B)
             from B 
             where A.A = A group by A)
 
select * from A

drop table A,B
 
Here is the result set I get when I run this query on my machine:

A           S           
----------- ----------- 
1           1
2           2
3           3
 
In my query above, I used the correlated subquery to update column A in table A with the sum of column B in table B for rows that have the same value in column A as the row being updated.

Conclusion

Let me summarize. A subquery and a correlated subquery are SELECT queries coded inside another query, known as the outer query. The correlated subquery and the subquery help determine the outcome of the result set returned by the complete query. A subquery, when executed independent of the outer query, will return a result set, and is therefore not dependent on the outer query. Where as, a correlated subquery cannot be executed independently of the outer query because it uses one or more references to columns in the outer query to determine the result set returned from the correlated subquery. I hope that you now understand the different of subqueries and correlated subqueries, and how they can be used in your T-SQL code.

source : http://www.databasejournal.com/features/mssql/article.php/3485291/Using-a-Correlated-Subquery-in-a-T-SQL-Statement.htm

CASE

The CASE function is a very useful T-SQL function. With this function you can replace a column value with a different value based on the original column value. An example of where this function might come in handy is where you have a table that contains a column named SexCode, where 0 stands for female, 1 for male, etc., and you want to return the value "female" when the column value is 0, or "male" when the column value is 1, etc.. This article will discuss using the CASE function in a T-SQL SELECT statement.
The CASE function allows you to evaluate a column value on a row against multiple criteria, where each criterion might return a different value. The first criterion that evaluates to true will be the value returned by the CASE function. Microsoft SQL Server Books Online documents two different formats for the CASE function. The "Simple Format" looks like this:

CASE input_expression 
    WHEN when_expression THEN result_expression 
        [ ...n ] 
    [ 
        ELSE else_result_expression 
    ] 
END
And the "Searched Format" looks like this:
CASE
    WHEN Boolean_expression THEN result_expression 
        [ ...n ] 
    [ 
        ELSE else_result_expression 
    ] 
END
 
Where the "input_expression" is any valid Microsoft SQL Server expression, the "when_expression" is the value in which the input_expression is compared, the "result_expression" is the value that will be return for the CASE statement if the "when_expression" evaluates to true, "[...n]" represents that multiple WHEN conditions can exist, the "else_result_expression" is the value that will be returned if no "when_expression" evaluates to true and in the "Searched Format" the "Boolean_expression" is any Boolean express that when it evaluates to true will return the "result_expression". Let me go through a couple of examples of each format to help you better understand how to use the CASE function in a SELECT statement.
For the first example let me show you how you would use the CASE function to display a description, instead of a column value that contains a code. I am going to use my earlier example that I described at the top of this article where I discussed displaying "female" or "male" instead of the SexCode. Here is my example T-SQL Code:

create table patients (PatientID int identity, 
                       PatientName varchar(50), 
                       PatientSexCode int)
insert into patients(PatientName, PatientSexCode) 
            values ('Doe, Jane', 0)
insert into patients(PatientName, PatientSexCode) 
            values ('Doe, Dick', 1)
insert into patients(PatientName, PatientSexCode) 
            values ('Doe, Spot', 2)
insert into patients(PatientName, PatientSexCode) 
            values ('xxxxxxxx', 9)
select PatientName,
       case PatientSexCode
        when 0 then 'female'
        when 1 then 'male'
        when 2 then 'unknown'
        else 'Invalid PatientSexCode' end as "Patient Sex"
      from patients
 
Here is the output from this T-SQL code:

PatientName                 Patient Sex            
--------------------------- -----------------------
Doe, Jane                   female
Doe, Dick                   male
Doe, Spot                   unknown
xxxxxxxx                    Invalid PatientSexCode
 
This example shows the syntax in action for a CASE function using the "Simple Format". As you can see the CASE function evaluates the PatientSexCode to determine if it is a 0, 1, or 2. If it is a 0, then "female" is displayed in the output for the "Patient Sex" column. If the PatientSexCode is 1, then "male" is display, or if PatientSexCode is 2 then "unknown" is displayed. Now if the PatientSexCode is anything other than a 0, 1 or 2 then the "ELSE" condition of the CASE function will be used and "Invalid PatientSexCode" will be displayed for the "Patient Sex" column.
Now the same logic could be written using a "Searched Format" for the CASE function. Here is what the SELECT statement would look like for the "Searched Format":

select PatientName,
       case 
        when PatientSexCode = 0 then 'female'
        when PatientSexCode = 1 then 'male'
        when PatientSexCode = 2 then 'unknown'
        else 'Invalid PatientSexCode' end as "Patient Sex"
      from patients
 
Note the slight differences between the "Simple" and "Searched" formats. In the "Simple" format I specified the column name for which row values will be compared against the "when_expressions" ,where as in the "Searched" format each WHEN condition contains a Boolean expression that compares the PatientSexCode column against a code value.
Now the CASE function can be considerably more complex than the basic examples I have shown. Suppose you want to display a value that is based on two different columns values in a row. Here is an example that determines if a Product in the Northwind database is of type Tins or Bottles, and is not a discontinued item.

Select  top 8 ProductName, 
       case 
        when QuantityPerUnit like '%Tins%' and
             Discontinued = 0 
          then 'Tins'
        when QuantityPerUnit like '%bottles%' and 
             Discontinued = 0 
          then 'Bottles'
        else 'Not Tins, Not Bottles, or is Discontinued'
        end 'Type or Availability'
   from Northwind.dbo.Products
   order by ProductName
 
The output for the above command on my server displays the following:

ProductName             Type or Availability                      
----------------------- ----------------------------------------- 
Alice Mutton            Not Tins, Not Bottles, or is Discontinued
Aniseed Syrup           Bottles
Boston Crab Meat        Tins
Camembert Pierrot       Not Tins, Not Bottles, or is Discontinued
Carnarvon Tigers        Not Tins, Not Bottles, or is Discontinued
Chai                    Not Tins, Not Bottles, or is Discontinued
Chang                   Bottles
Chartreuse verte        Not Tins, Not Bottles, or is Discontinued
 
As you can see I'm using a "Searched Format" for this CASE function call. Also, each WHEN clause contains two different conditions. One condition to determine the type (tins, or bottles) and another condition to determine if the product has been discontinued. If the QuantityPerUnit contains the string "Tins" and the Discontinue column value is 0 then the "Type of Availability" is set to "Tins". If the QuantityPerUnit contains the string "Bottles" and the Discontinue column value is 0 then the "Type of Availability" is set to "Bottles". For all other conditions, the "Type or Availability" is set to "Not Tins", "Not Bottles", or is "Discontinued."
The WHEN clauses in the CASE function are evaluated in order. The first WHEN clause that evaluates to "True" determines the value that is returned from the CASE function. Basically, multiple WHEN clauses evaluate to "True", only the THEN value for the first WHEN clause that evaluates to "True" is used as the return value for the CASE function. Here is an example where multiple WHEN clauses are "True."

select top 5 title, 
       case
         when price < 12.00 then 'Cheap'
         when price < 3.00  then 'Really Cheap'
         when price > 12.00 and price < 20.00 then 'Average'
         else 'Expensive' end 'Price Category'
  from pubs.dbo.titles
 
The output on my machine for this query looks like this:

title                                                    Price Category 
-------------------------------------------------------- ------------ 
The Busy Executive's Database Guide                      Average
Cooking with Computers: Surreptitious Balance Sheets     Cheap
You Can Combat Computer Stress!                          Cheap
Straight Talk About Computers                            Average
Silicon Valley Gastronomic Treats                        Average
 
If you look at the raw titles table data in the pubs database for the title "You Can Combat Computer Stress!" you will note that the price for this book is $2.99. This price makes both the "price < 12.00" and "price < 3.00" conditions "True". Since the conditions are evaluated one at a time, and the "price < 12.00" is evaluated prior to the "price < 3.00," the "Price Category" for the title "You Can Combat Computer Stress!" is set to "Cheap".
The CASE function can appear in different places within the SELECT statement, it does not have to only be in the selection list within the SELECT statement. Here is an example where the CASE function is used in the WHERE clause.

select top 5 title, price
  from pubs.dbo.titles
  where 
     case
         when price < 12.00 then 'Cheap'
         when price < 3.00  then 'Really Cheap'
         when price > 12.00 and price < 20.00 then 'Average'
         else 'Expensive' end = 'Average'
 
The output for this query looks like this:

title                                                    price                 
-------------------------------------------------------- -------------- 
The Busy Executive's Database Guide                      19.9900
Straight Talk About Computers                            19.9900
Silicon Valley Gastronomic Treats                        19.9900
Prolonged Data Deprivation: Four Case Studies            19.9900
Sushi, Anyone?                                           14.9900
 
Here I only wanted to display books from the titles table in pubs database if the price category is 'Average'. By placing my CASE function in the WHERE clause I was able to accomplish this.

Conclusion

As you can see the CASE function is an extremely valuable function. It allows you to take a data column and represent it differently depending on one or more conditions identified in the CASE function call. I hope that the next time you need to display or use different values for specific column data you will review the CASE function to see if it might meet your needs.

source : http://www.databasejournal.com/features/mssql/article.php/3288921/T-SQL-Programming-Part-5---Using-the-CASE-Function.htm

BREAK and CONTINUE Statements


Now sometimes you want to build a loop that will process through logically to the end most of the time, but not all the time. In other words, you may want to break out of the loop if some particular condition arises. Also in addition to breaking out of the loop, you may not want to process all the code in the loop before going back to the top of the loop and starting through the next iteration of the loop. For these kinds of programming requirements SQL Server provides the BREAK and CONTINUE statements.
The BREAK statement exits out of the inner most WHILE loop, and proceeds to the statement following the END statement that is associated with the loop in which the BREAK statement is executed. The CONTINUE statement skips executing the rest of the statements between the CONTINUE statement and the END statement of the current loop and starts executing at the first line following the BEGIN statement of the current WHILE loop. Let's go though a couple of BREAK and CONTINUE examples.
For the BREAK statement I'm going to modify my last example that generated PART table records. This time I'm going to BREAK out of the inner WHILE loop when Category_ID is 2 and PART_ID is 1. Here is my code for the BREAK statement.
declare @Part_Id int
declare @Category_Id int
declare @Desc varchar(50)
create table PART (Part_Id int, Category_Id int, Description varchar(50))
set @Part_Id = 0
set @Category_Id = 0 
while @Part_Id < 2
begin
  set @Part_Id = @Part_Id + 1
  while @Category_Id < 3
  begin
    set @Category_Id = @Category_Id + 1 
    If @Category_ID = 2 and @Part_ID = 1
      Break
    set @Desc = 'Part_Id is ' + cast(@Part_Id as char(1)) +
        ' Category_Id ' + cast(@Category_Id as char(1))
    insert into PART values(@Part_Id, 
                     @Category_Id,
                     @Desc )
  end  
  set @Category_Id = 0 
end
select * from PART
drop table PART
Here is the output for this code that contains a BREAK statement inside the inner WHILE loop.
 Part_Id     Category_Id Description                                        
 ----------- ----------- ----------------------------------------- 
 1           1           Part_Id is 1 Category_Id 1
 2           1           Part_Id is 2 Category_Id 1
 2           2           Part_Id is 2 Category_Id 2
 2           3           Part_Id is 2 Category_Id 3
From this output you can see that no records were inserted for Part_Id = 1 and Category_Id =2 or 3, where as there are records for Part_Id = 2 with all values for the Category_Id column. This is because the IF statement in the inner loop forced the BREAK statement to exit the inner loop. Since there were records generate for Part_Id = 2, shows that the BREAK statement only exited the inner loop and not the outer loop.
Now just to stay with the same example I've been using, let's replace the BREAK statement in the code above with a CONTINUE statement. Here is the code for demonstrating the CONTINUE statement.
 declare @Part_Id int
 declare @Category_Id int
 declare @Desc varchar(50)
 create table PART (Part_Id int, Category_Id int, Description varchar(50))
 set @Part_Id = 0
 set @Category_Id = 0 
 while @Part_Id < 2
 begin
   set @Part_Id = @Part_Id + 1
   while @Category_Id < 3
   begin
     set @Category_Id = @Category_Id + 1 
     If @Category_ID = 2 and @Part_ID = 1
       Continue
     set @Desc = 'Part_Id is ' + cast(@Part_Id as char(1)) +
                 ' Category_Id ' + cast(@Category_Id as char(1))
     insert into PART values(@Part_Id, 
                             @Category_Id,
                             @Desc )
   end  
   set @Category_Id = 0 
 end
 select * from PART
 drop table PART
When you use the CONTINUE statement you get the following output.
 ----------- ----------- ----------------------------------------- 
 1           1           Part_Id is 1 Category_Id 1
 1           3           Part_Id is 1 Category_Id 3
 2           1           Part_Id is 2 Category_Id 1
 2           2           Part_Id is 2 Category_Id 2
 2           3           Part_Id is 2 Category_Id 3
As you can see, when I use the CONTINUE statement only the record with Category_Id = 2 and Part_Id = 1 is missing. This is because the CONTINUE statement does not break out of the inner WHILE loop but only goes back to the top of the WHILE loop without inserting the record. This happens only when Category_Id is 2 and Part_Id is equal to 1. When Part_Id = 1 and Category_Id = 3 the insert statement is still executed.



GOTO Statement

The BREAK statement will only exit you from the currently processing WHILE loop, it will not break out of all WHILE loops. However, occasionally this is the kind of functionality your T-SQL script needs. To have your code break out of all WHILE loops, no matter how many nested WHILE statements you have, you will need to use the GOTO statement. Now I know most programmers cringe at the thought of using the GOTO statement, but in this case I feel the GOTO is an except able practice. Using my same example I will use the GOTO to break out of both WHILE loops, when the PART_Id = 1 and the Category_ID=3.
 declare @Part_Id int
 declare @Category_Id int
 declare @Desc varchar(50)
 create table PART (Part_Id int, Category_Id int, Description varchar(50))
 set @Part_Id = 0
 set @Category_Id = 0 
 while @Part_Id < 2
 begin
   set @Part_Id = @Part_Id + 1
   while @Category_Id < 3
   begin
     set @Category_Id = @Category_Id + 1 
     If @Category_ID = 3 and @Part_ID = 1
       GOTO BREAK_OUT
     set @Desc = 'Part_Id is ' + cast(@Part_Id as char(1)) +
                 ' Category_Id ' + cast(@Category_Id as char(1))
     insert into PART values(@Part_Id, 
                             @Category_Id,
                             @Desc )
   end  
   set @Category_Id = 0 
 end
 BREAK_OUT:
 select * from PART
 drop table PART
Here is the output from this GOTO code:
 Part_Id     Category_Id Description                                        
 ----------- ----------- ----------------------------------------- 
 1           1           Part_Id is 1 Category_Id 1
 1           2           Part_Id is 1 Category_Id 2
Here the GOTO logic stopped the insertion of records into the PART table when @Category_ID = 3 and @Part_Id = 1. This is done by executing the "GOTO BREAKOUT" statement. Note that when this GOTO statement was executed it branched to the label "BREAK OUT:" which can be found following the END statement for the first, outer most WHILE statement.

Conclusion

Hopefully now you have a better idea of how to code a T-SQL WHILE loop. I've explained how to control the WHILE loop, break out of a loop by using the BREAK statement, use the CONTINUE statement to skip some of the code in the while loop, and/or break out of all WHILE loops using the GOTO statement. The techniques I've described should give you the basis for building all your WHILE statements from a single WHILE loop to a complex set of nested WHILE loops. My next article in this series will discuss how to process through a set of records.

source : http://www.databasejournal.com/features/mssql/article.php/10894_3100621_2/T-SQL-Programming-Part-2---Building-a-T-SQL-Loop.htm

WHILE Statement

In T-SQL the WHILE statement is the most commonly used way to execute a loop. Here is the basic syntax for a WHILE loop:
 WHILE <Boolean expression> <code block>
Where a <Boolean expression> is any expression that equates to a true or false answer, and the <code block> is the desire code to be executed while the <Boolean expression> is true. Let's go through a real simple example.
In this example I will increment a counter from 1 to 10 and display the counter each time through the WHILE loop.
 declare @counter int
 set @counter = 0
 while @counter < 10
 begin
   set @counter = @counter + 1
   print 'The counter is ' + cast(@counter as char)
 end
Here the code executes the WHILE statement as long as the @counter integer variable is less than 10, this is the Boolean expression of the WHILE loop. The @counter variable starts out at zero, and each time through the WHILE loop it is incremented by 1. The PRINT statement displays the value in the @counter variable each time through the WHILE loop. The output from this sample looks like this:
 The counter is 1                             
 The counter is 2                             
 The counter is 3                             
 The counter is 4                             
 The counter is 5                             
 The counter is 6                             
 The counter is 7                             
 The counter is 8                             
 The counter is 9                             
 The counter is 10        
As you can see, once the @counter variable reaches 10 the Boolean expression that is controlling the WHILE loop is no longer true, so the code within the while loop is no longer executed.
Not only can you have a single while loop, but you can have WHILE loops inside WHILE loops. Or commonly know as nesting of WHILE loops. There are lots of different uses where nesting is valuable. I commonly use nesting of WHILE loops to generate test data. My next example will use the WHILE loop to generate test records for a PART table. A given PART record is uniquely identified by a Part_Id, and a Category_Id. For each Part_Id there are three different Category_Id's. Here is my example that generates 6 unique records for my PART table using a nested WHILE loop.
 declare @Part_Id int
 declare @Category_Id int
 declare @Desc varchar(50)
 create table PART (Part_Id int, Category_Id int, Description varchar(50))
 set @Part_Id = 0
 set @Category_Id = 0 
 while @Part_Id < 2
 begin
   set @Part_Id = @Part_Id + 1
   while @Category_Id < 3
   begin 
     set @Category_Id = @Category_Id + 1
     set @Desc = 'Part_Id is ' + cast(@Part_Id as char(1)) +
                 ' Category_Id ' + cast(@Category_Id as char(1))
     insert into PART values(@Part_Id, 
                             @Category_Id,
                             @Desc )
   end  
   set @Category_Id = 0 
 end
 select * from PART
 drop table PART
Here is the output from the SELECT statement at the bottom of this nested WHILE loop example.
 Part_Id     Category_Id Description                                        
 ----------- ----------- ----------------------------------------- 
 1           1           Part_Id is 1 Category_Id 1
 1           2           Part_Id is 1 Category_Id 2
 1           3           Part_Id is 1 Category_Id 3
 2           1           Part_Id is 2 Category_Id 1
 2           2           Part_Id is 2 Category_Id 2
 2           3           Part_Id is 2 Category_Id 3
As you can see, by using a nested WHILE loop each combination of Part_Id and Category_Id is unique. The code within the first WHILE loop controlled the incrementing of the Part_Id, where as the second WHILE loop set the Category_Id to a different value each time through the loop. The code within the first while loop was executed only twice, but the code inside the second WHILE loop was executed 6 times. Thus giving me 6 sample PART records.

source :  http://www.databasejournal.com/features/mssql/article.php/3100621/T-SQL-Programming-Part-2---Building-a-T-SQL-Loop.htm