VBA: What Type Are Your Constants?

In the previous post we saw a common mistake when declaring VBA variables and used the Locals window to show that variables are Variant types unless you specify otherwise by using:

Constants behave a little differently to variables so let’s finish off this topic by taking a look at them too.

Syntactical Difference Between Variables And Constants

A key point that we’re interested in here is that, in VBA,  you may not assign a value to a variable when you declare it but, with a constant, you must. Let’s quickly cover the four combinations to prove it:

1 Variable Declaration And Assignment Together

Sub Main()

    'may not assign value with variable
    'so this will not compile
    Dim strVariable1 As String = "Hello"

End Sub

Variable Value Assignment Compile Error

2 Variable Declaration And Assignment Separate

Sub Main()

    'declaration and assignment are separate, so this is fine
    Dim strVariable1 As String
    strVariable1 = "Hello"

End Sub

Variable Value Assignment Separate

3 Constant Declaration And Assignment Separate

Sub Main()

    'must assign value with declaration
    'so this will not compile
    Const strCONSTANT1 As String
    strCONSTANT1 = "Hello"

End Sub

Constant Value Assignment Compile Error

  • Tip: A commonly used convention in VBA is to capitalise constants, so my constant’s name is strCONSTANT1 rather than strConstant1.

4 Constant Declaration And Assignment Together

Sub Main()

    'constant declaration and assignment together
    'so this will compile
    Const strCONSTANT1 As String = "Hello"

End Sub

Constant Value Assignment Together

What Happens If You Don’t Specify A Constant’s Type?

In the correct constant example (4) above I explicitly declared my constant as a String type. However, as with variables, the VBA compiler does not require you to specify the constant’s type when you declare it, so the following code is perfectly legitimate:

Sub Main()

    Const strHELLO = "Hello", strGOODBYE = "Goodbye"

End Sub

Implicit Constant String Types

If you check out the Locals window you’ll notice that both constants are String types even though I haven’t specified their type in the code. This is different to what happens with variables.

  • If you do not specify the constant’s type by using either As Type in the declaration or a type declaration character at the end of the constant’s name, then the compiler will interpret the type of the value you’re assigning to it to determine what type the constant should be.
  • DefType statements do not affect constants

When it comes to numbers, the compiler’s interpretation is as follows:

  • Whole numbers between -32,768 and 32,767 (inclusive) will be Integer types.
  • Whole numbers which are outside the range of an Integer but are between -2,147,483,648 and 2,147,483,647 (inclusive) will be Long types.
  • All other numbers will be Double types.
Sub Main()

     Const intMIN = 1
     Const lngMAX = 40000
     Const dblLOW = 2.1

End Sub

Constant Numbers Interpreted

You can, however, use type characters at the end of the numbers to coerce them to be different types to the default. For example, Const lngMIN = 1& would make lngMIN a Long because & is the type character for a Long type.

What Happens If You Do Specify The Constant’s Type?

If you do specify the constant’s type then that’s what the compiler will use. If the value you assign to the constant is of a different type then it will be converted (if possible) into the same type as the constant when the constant is initialised. Let’s have a look at some examples.

Const lngMIN As Long = 1

Here the constant’s type is explicitly given as a Long, but the value we’re assigning it is an Integer. In this case the 1 will be converted to a Long when the constant is initialised.

Similarly:

Const lngMIN As Long = "1"

The "1" String will be coerced into a 1 Long when the constant is initialised.

However, the following would result in a compile error because the String "Hello" cannot be converted into a Long:

Const lngMIN As Long = "Hello"

Conclusion

There’s a lot of code in this post which I don’t like so let me finish off with a best practice tip. Just as with variables, you should always explicitly state your constants’ types when you declare them. This makes your code easy to read and ensures that your constants will be the type you want them to be. Should you find yourself reading someone else’s code where this hasn’t been done then at least now you have this background information to refer to.

Posted in Microsoft Excel, Microsoft Office | Tagged , , , , , , , , | Leave a comment

A Common Mistake When Declaring Variables In VBA

For today’s post I’d like you to imagine that you’re an up and coming VBA programmer who is starting to feel at home with the IDE and language. You’ve read about some VBA best practices which has made you aware of the benefits of Option Explicit, so you’ve started to dutifully declare your variables and you try to carefully choose what types they should be. Good on you, but be warned: you’re a prime candidate for falling foul of one of VBA’s syntactical nuances!

Let’s have a look at some code.

Option Explicit

Sub HowNotToDeclareYourVariables()

    Dim rngStartDate, rngEndDate As Range

    'do some stuff with rngStartDate and rngEndDate

End Sub

So here I’ve declared two variables called rngStartDate and rngEndDate. The variable names are meaningful and I’ve prefixed them with rng which is the prefix I always use to indicate that they’re a Range type.

Unfortunately I’ve made a mistake. Let’s step into the code by pressing F8 and have a look in the Locals Window to see what type they are.

VariableMistake1

rngEndDate is a Range type as you’d expect, but have a closer look at rngStartDate. It’s a Variant.  In VBA, if you declare multiple variables using a single Dim (or similar, eg. Private) keyword, then you must explicitly state the type of each variable. If you don’t then they’ll all be Variant types apart from the last one which’ll be whatever type you’ve given it.

Let’s write the code so both variables are explicitly declared as Range types.

Sub HowNotToDeclareYourVariables()

    Dim rngStartDate As Range, rngEndDate As Range

    'do some stuff with rngStartDate and rngEndDate

End Sub

And now check it in the Locals window:

VariableMistake2

Of course, a perfectly fine and safe option would be to declare the variables on separate lines:

Sub HowToDeclareYourVariables()

    Dim rngStartDate As Range
    Dim rngEndDate As Range

    'do some stuff with rngStartDate and rngEndDate

End Sub

VariableMistake3

So there you have it, but that’s not quite the end of the story. What makes things slightly more confusing is that, whilst this rule also holds up in VB6, things were changed in VB.Net. You need to be aware of this for when you’re reading VB.Net code snippets online. In VB.Net, the following code is quite correct in its intention to declare both variables as Range types:

VariableMistake4

That’s all for now. I hope this saves you a few headaches and, until next time, happy coding.

Posted in .Net, Microsoft Excel, Microsoft Office, VB .Net | Tagged , , , , , , | 4 Comments

Calculate The Absolute Sum in Excel

A colleague of mine asked me today how to go about using MS Excel formulas to calculate the sum of absolute values from a given dataset. This question crops up quite often on the forums so I thought I’d put together a quick blog post on it. There isn’t a built-in SUMABS() (or equivalent) worksheet function so you have to do a little bit of work to get the right answer.

So here’s our sample data:

ABSSUMSampleData

We can see that the sum of A2:A8 would give a result of -60 but, if we were to consider the absolute values (the numbers without their – sign) then the result would be 180.

= -10 + 10 + 20 + -20 + 30 + -40 + -50 = -60

= 10 + 10 + 20 + 20 + 30 + 40 + 50 = 180

Option 1 – Use A Helper Column

In my opinion, the best way to do this is to use a helper column. In cell B2 put the formula =ABS(A2) and then fill down to B8. The ABS() worksheet function returns the absolute value, so now we can just take the sum of B2:B8 and it’ll give us a result of 180.

=SUM(B2:B8)

In my example, I’ve actually got A1:A8 set up as a table, so when I added the =ABS(A2)formula into B2, Excel automatically expanded the table and filled the formula down the column for me. I then navigated to the Table Design tab on the ribbon, ticked the Total Row checkbox and it automatically inserted a formula to get the total:

ABSSUMHelperColumn

The SUBTOTAL() formula it inserted is just a fancy version of the =SUM(B2:B8) formula I mentioned a minute ago. It gives exactly the same result – it sums the numbers – but it also ignores any numbers which have been hidden should you start to apply filtering or manually hide some of the table rows. There are a few other differences between them so have a read through the help file topic on SUBTOTAL() if you’re unfamiliar with it.

I think the helper column approach is particularly good because it is simple and it gives a lot of flexibility if you want to use the data further - such as in a chart or in a pivot table. The helper column can also be used to sort the data by absolute values.

Okay, that’s all well and good, but what if you just want to do it in a single formula?

Option 2 – Use A SUM() Array Formula Or SUMPRODUCT()

Using an array formula or SUMPRODUCT() is a brute force approach to get the job done.

ABSSUMPRODUCT

{=SUM(ABS(A2:A8))}

=SUMPRODUCT(ABS(A2:A8))

Given that we can actually use a more efficient SUMIF() formula to give the same result (covered in option 3), I’d suggest that this option is the one which generally shouldn’t be used. It’s true that these formulae are absolutely fine on a small dataset such as this, but when your data starts to get large and you have more and more heavyweight formulas in your worksheet, you’ll notice that it starts to slow down.

Option 3 – Use SUMIF()

I think this formula is pretty cute – it’s similar to the SUMIF() approach to get a sum between two dates.

=SUMIF(A2:A8,">0") - SUMIF(A2:A8,"<0")

which can also be written as

=SUM(SUMIF(A2:A8,{">0","<0"})*{1,-1})

ABSSUMIF

This formula takes the sum of the positive numbers and then subtracts the sum of the negative numbers. If we break down the first version:

=SUMIF(A2:A8,">0") - SUMIF(A2:A8,"<0")

evaluates to:

=60 - -120

which evaluates to:

=180

And, for completeness, if we break down the second version:

=SUM(SUMIF(A2:A8,{">0","<0"})*{1,-1})

evaluates to:

=SUM({60,-120}*{1,-1})

which evaluates to:

=SUM({60,120})

which evaluates to

=180

Well, I think that pretty much covers it. If you use a different approach to calculating the absolute sum then post a comment and share it with us.

Posted in Microsoft Excel, Microsoft Office | Tagged , , , , , , | 2 Comments

Conditional Average On Non-Contiguous Ranges Using FREQUENCY()

At the beginning of the year I talked about the FREQUENCY() worksheet function and gave a handful of examples on how it can be used. Today’s article is another, brilliant FREQUENCY() example which was posted by Barry Houdini on the MrExcel board. I’ve picked up quite a few formula tricks from Barry over the years and this one is up there with the best of them. Barry humbly tells me that he in turn picked up the technique from Aladin Akyurek, another expert on the MrExcel board, so full credit to both of them.

The Problem

We have some phone call information about three people working in a customer services team.

ConditinalAverageFreqData

The count of phone calls is split into two types, ACD and AMS, for each person and we need to get the ACD mean average from the data set. We’ve also been told that the average should not take into account any 0 values in the cells so the correct answer would be 56:

(24 + 21 + 99 + 67 + 87 + 6 + 88) / 7 = 56

In this case we want to do a conditional average: we want to ignore cells which contain 0′s. Usually we could do this by using the AVERAGEIF() function but we can’t do that here because the ACD data is in three separate, or non-contiguous, ranges. This formula will return a #VALUE! error because AVERAGEIF() can’t handle non-contiguous ranges:

=AVERAGEIF((B3:B7,D3:D7,F3:F7),"<>0")

To get an average from a non-contiguous set of ranges we could usually use the SUM() and COUNT() worksheet functions like so:

=SUM(B3:B7,D3:D7,F3:F7)/COUNT(B3:B7,D3:D7,F3:F7)

The problem is the COUNT() will include the 0′s, so the formula returns a result of 26.13 which is incorrect. We could try to adjust the formula to ignore zeros by using COUNTIF() instead of COUNT(), but COUNTIF() can’t be used on non-contiguous ranges either so this will also return #VALUE!:

=SUM(B3:B7,D3:D7,F3:F7)/COUNTIF((B3:B7,D3:D7,F3:F7),"<>0")

So the question is how can we get a count of non-zero values from those cells?

The Solution

The solution Barry posted to this quandary is as follows:

=SUM(B3:B7,D3:D7,F3:F7)/INDEX(FREQUENCY((B3:B7,D3:D7,F3:F7),0),2)

Note that this formula does not need to be CTRL+SHIFT+ENTER’d.

The SUM() part of the formula is straightforward enough, but let’s have a closer look at the rest of it. If you feel that you need a quick refresher on the FREQUENCY() function then take a look at my previous blog entry.

FREQUENCY((B3:B7,D3:D7,F3:F7),0)

The key point is that FREQUENCY() can be used on non-contiguous ranges: the data_array is (B3:B7,D3:D7,F3:F7). The bins_array is 0, so FREQUENCY() will return an array of two values: a count of the ACD numbers which fall into the first bucket of 0, and a count of the ACD numbers which are greater than 0:

FREQUENCY((B3:B7,D3:D7,F3:F7),0)

evaluates to

{8;7}

It’s a safe assumption that there will not be any negative numbers in this particular data set so the 8 is the count of values which are exactly equal to 0 and the 7 is the count of values which are greater than 0. The 7 is the number we’re interested in, so next we use the INDEX() function to extract it from the array:

INDEX({8;7},2)

evaluates to

{7}

and then we divide the sum of the values by 7 to get the correct answer of 56.

SUM(B3:B7,D3:D7,F3:F7)/{7}

evaluates to:

392/{7}

evaluates to our final answer:

{56}

The formula will still work if there are empty cells or even if the non-contiguous ranges are different sizes. Pretty slick.

Posted in Microsoft Excel, Microsoft Office | Tagged , , , , , , , , , | 3 Comments

Excel 2013 Selection Colour and Theme Editor

If you ever want to change the way Excel highlights selected cells on a worksheet then you won’t have much luck scrolling through Excel’s options because, prior to Excel 2013,  it’s controlled by the Windows Appearance settings.

In Windows 7 the setting can be found under Control Panel > Appearance and Personalization > Personalization > Window Color and Appearance > Advanced Appearance Settings. The item of interest is ‘Selected Items’.

Windows Settings Selected Cells

If you decide to go crazy with your selection colour then be careful because this setting is used universally.

In Excel 2013 things have changed and, whilst one can change the colour of the grid using the ‘Window’ item option in the Window Color and Appearance settings, there doesn’t seem to be a way of changing the selection colour to something other than that grey. You know the one I’m talking about…

Excel selected cells 2013

There’s just too much grey on that screen for me and I’m not a fan of the grey and green combination. The problem is that the Dark Gray Office theme is the only theme which I think is remotely half decent (at time of writing there’s only a limited choice of three themes) so, for now, the sea of grey is something which has to be tolerated.

The solution to all of this is simple: Microsoft could release a Color Theme Editor for Office 2013 which does a similar job to their Color Theme Editor for Visual Studio 2012. For example, its Blue theme looks far better than the two themes (yes, only two) which are available out of the box and is a close match to Visual Studio 2010:

VS 2012 Blue

I think that’d be pretty cool but if that’s too much to ask for then I guess an update with some new, built-in themes would be okay too.

What do you think of Excel 2013′s general appearance compared to previous versions? I haven’t upgraded to Windows 8 yet so I’d also be interested to hear how well you think their appearances gel together. If you like the idea of a Color Theme Editor for Office 2013 then post a comment to say so: you never know, someone from Microsoft might be reading.

Posted in Microsoft Excel | Tagged , , , , , | 3 Comments

Recently Used Files Disappearing

The recently used files list is a really handy feature in Excel (and other Office applications) which allows you to quickly open workbooks which you’ve been previously working on and have saved. In more recent versions of Excel you can also pin the workbooks you use the most so they don’t drop off the list. This Microsoft article has some useful information on customising the recently used files list in Excel 2010, including:

  • Change the number of files that appear in the list of recently used files
  • Keep a file on the Recent Documents list
  • Add a quick access list to the Backstage file navigation bar
  • Clear the list of recently used files

There have been a few recent threads on the online forums where users complained that their recently used files list had been mysteriously cleared. The good news is that this wasn’t because of a horrible bug: as it turns out, an application called CCleaner was to blame.

CCleaner (not to be confused with Rob Bovey’s CodeCleaner) is a free PC optimisation and cleaning tool by Piriform. It’s a great piece of kit which I’ve been using for years and highly recommend. The features I like the most are the registry cleaner and the StartUp monitor which lets you disable certain programs from running on startup. One thing to be aware of though is that CCleaner will clear any recently used files lists from your Office applications. Fortunately (or as one would expect from a good piece of software) there’s a setting you can toggle which will stop this happening. If you start up CCleaner, go to the Cleaner tab on the left and then the Applications tab at the top, you’ll find an Applications section.

CCleaner

All you need to do is untick the relevant Office checkboxes and CCleaner will leave your recently used files list alone.

Posted in Microsoft Excel, Microsoft Office | Tagged , , | Leave a comment

Phantom Breakpoints

I had a horrific Excel 2003 crash today. When I restarted Excel and opened any workbooks – including locked xla’s - which had been open during the crash, I found that they were riddled with phantom breakpoints. I’ve seen the occasional phantom breakpoint before, but never on this scale.

So what is a phantom breakpoint? A phantom breakpoint is a term people use to describe a situation where they try to run some code and, for no apparent reason, code execution pauses when a certain line is reached – just as it would if you had placed a breakpoint there. The pause in code execution is accompanied by the message “code execution has been interrupted”. When you press F5 to continue code execution, it will happily finish without any complaints (unless it hits another phantom breakpoint). My understanding from participating on online MS Office forums is that phantom breakpoints are more common in MS Access than in MS Excel.

In the past, the reliable fix I’ve used to get rid of the phantom breakpoints is to press CTRL+BREAK. Another less than ideal option is to put Application.EnableCancelKey = xlDisabled at the start of the problematic procedure. My usual solution didn’t work in this case so I tried a whole host of things including clearing xlb files, running Code Cleaner, pressing CTRL+SHIFT+F9 as suggested here and various other tweaks – all to no avail.

I also have Excel 2007 installed on the same box and I found that the workbooks had the same problem when I opened them in that.  In the end I rebooted my PC and the problem disappeared, so the cause must be a temporary file which is communal across versions. Any ideas?

Posted in Microsoft Excel, Microsoft Office | Tagged , | 1 Comment

SQL Server: Using Table Aliases In Delete And Update Queries

A couple of posts ago I said that I would blog about counting unique and distinct values using VBA. I promise I will get to that but today I want to talk about the syntax for using tables aliases in UPDATE and DELETE statements in SQL Server because it’s something I use all the time and I think is a fantastic tip.

First of all, let’s set the scene. Here I’ve created a temp table called #Customers containing four rows:

IF OBJECT_ID('tempdb..#Customers') IS NOT NULL
	DROP TABLE #Customers

CREATE TABLE #Customers
(
FirstName VARCHAR(20),
LastName VARCHAR(20)
)

INSERT INTO #Customers
VALUES ('Colin','Legg')
, ('John', 'Smith')
, ('John', 'Legg')
, ('Colin', 'Smith')

SELECT *
FROM #Customers

When running the code you’ll get this output:

(4 row(s) affected)

FirstName            LastName
-------------------- --------------------
Colin                Legg
John                 Smith
John                 Legg
Colin                Smith

(4 row(s) affected)

Suppose we want to delete Colin Legg and John Smith from the table. That’s straightforward enough and can be done as follows:

DELETE
FROM #Customers
WHERE (FirstName = 'Colin' AND LastName = 'Legg')
OR (FirstName = 'John' AND LastName = 'Smith')

SELECT *
FROM #Customers

When we run that we get two rows left which contain John Legg and Colin Smith:

(2 row(s) affected)
FirstName            LastName
-------------------- --------------------
John                 Legg
Colin                Smith

(2 row(s) affected)

So far so good, but it gets more complicated when you’re sourcing the customers you want to delete using information from another table. Let’s start again with this set-up:

IF OBJECT_ID('tempdb..#Customers') IS NOT NULL
	DROP TABLE #Customers

CREATE TABLE #Customers
(
FirstName VARCHAR(20),
LastName VARCHAR(20)
)

IF OBJECT_ID('tempdb..#CustomersToDelete') IS NOT NULL
	DROP TABLE #CustomersToDelete

CREATE TABLE #CustomersToDelete
(
FirstName VARCHAR(20),
LastName VARCHAR(20)
)

INSERT INTO #Customers
VALUES ('Colin','Legg')
, ('John', 'Smith')
, ('John', 'Legg')
, ('Colin', 'Smith')

INSERT INTO #CustomersToDelete
VALUES ('Colin','Legg')
, ('John', 'Smith')
, ('Robert', 'Jones')

SELECT *
FROM #Customers

SELECT *
FROM #CustomersToDelete

This time we have two temp tables and running the above code gives this output:

(4 row(s) affected)

(3 row(s) affected)

FirstName            LastName
-------------------- --------------------
Colin                Legg
John                 Smith
John                 Legg
Colin                Smith
(4 row(s) affected)

FirstName            LastName
-------------------- --------------------
Colin                Legg
John                 Smith
Robert               Jones
(3 row(s) affected)

Let’s say we want to delete the customers in the #Customers table if they’re listed in the #CustomersToDelete table. The first thing I do in these situations is write a SELECT query which will show me the rows I’m going to end up deleting. There are a few different ways this can be done (such as using INTERSECT or an INNER JOIN)  but here I’m going to use a correlated subquery:

SELECT *
FROM #Customers c
WHERE EXISTS (
	SELECT NULL
	FROM #CustomersToDelete ctd
	WHERE c.FirstName = ctd.FirstName
	AND c.LastName = ctd.LastName)

Correlated subqueries aren’t anything to be afraid of. The subquery is the query nested inside the outer query:

SELECT *
FROM #Customers c
WHERE EXISTS (
	SELECT NULL	
	FROM #CustomersToDelete ctd
	WHERE c.FirstName = ctd.FirstName 
	AND c.LastName = ctd.LastName)

And it’s correlated because the subquery and the outer query are talking to one another. You’ll notice that the ‘c’ table alias in the outer query is also used in the subquery.

This query returns 2 rows because Robert Jones doesn’t exist in the #Customers temp table:

FirstName            LastName
-------------------- --------------------
Colin                Legg
John                 Smith

(2 row(s) affected)

Now that we’re happy that the SELECT query gives the rows we want to delete, we just have to convert it into a DELETE query. We can start by replacing the SELECT * with a DELETE:

DELETE
FROM #Customers c
WHERE EXISTS (
	SELECT NULL
	FROM #CustomersToDelete ctd
	WHERE c.FirstName = ctd.FirstName
	AND c.LastName = ctd.LastName)

Unfortunately that query isn’t going to run. The syntax is invalid and SSMS will start underlining words with red squiggly lines because it’s not happy: it’s the ‘c’ table alias that’s causing the problem. The next step is to look at the DELETE (T-SQL) syntax in the helpfile. It all looks quite confusing but, using the information in the arguments section, we can whittle down what we’re interested in to this:

DELETE 
    [ FROM ] 
    { table_alias }
    [ FROM table_source [ ,...n ] ] 
    [ WHERE {   } ]

And using that as our guide, we can update the query to this slightly unusual-looking beast:

DELETE
FROM c
FROM #Customers c
WHERE EXISTS (
	SELECT NULL
	FROM #CustomersToDelete ctd
	WHERE c.FirstName = ctd.FirstName
	AND c.LastName = ctd.LastName)

The notes in the arguments section of the helpfile explain that the first FROM is an optional keyword. Since there’s no recommendation on whether it should be left in or not, we can quite happily remove it from the query:

DELETE c
FROM #Customers c
WHERE EXISTS (
	SELECT NULL
	FROM #CustomersToDelete ctd
	WHERE c.FirstName = ctd.FirstName
	AND c.LastName = ctd.LastName)

When we run either of these we versions get a confirmation in the Results window that 2 rows were deleted and then if we check what’s left in the customers table we’ll see that John Legg and Colin Smith are still in there.

I use this type of query on a daily basis – you’ll be amazed at how often you’ll want to use table aliases for query readability so I can’t emphasise enough how useful it is. There are even situations when you’re forced to use table aliases, such as when you want to join a table onto itself (a self join) or when you have a correlated subquery where the same table is used in both the outer query and the subquery. Examples of the both of these situations can be found on MSDN here.

Moving on, it’s a very similar story if you want to do an UPDATE query with table aliases.

IF OBJECT_ID('tempdb..#Orders') IS NOT NULL
	DROP TABLE #Orders

IF OBJECT_ID('tempdb..#OrdersToUpdate') IS NOT NULL
DROP TABLE #OrdersToUpdate

CREATE TABLE #Orders
(
OrderNumber SMALLINT IDENTITY (1,1),
OrderPriority VARCHAR(6)
)

CREATE TABLE #OrdersToUpdate
(
OrderNumber SMALLINT
)

INSERT INTO #Orders
VALUES ('Low'),('Low'),('Low'),('Low')

INSERT INTO #OrdersToUpdate
VALUES (1),(4)

SELECT *
FROM #Orders

SELECT *
FROM #OrdersToUpdate

Running the above code gives us this output:

(4 row(s) affected)

(2 row(s) affected)
OrderNumber OrderPriority
----------- -------------
1           Low
2           Low
3           Low
4           Low

(4 row(s) affected)

OrderNumber
-----------
1
4

(2 row(s) affected)

In this case we want to change the priority of orders in the #Orders table to ‘High’ if they exist in the #OrdersToUpdate table. Again, we can start by writing a SELECT query to identify the orders we’ll be updating:

SELECT *
FROM #Orders o
WHERE EXISTS (
	SELECT NULL
	FROM #OrdersToUpdate otu
	WHERE o.OrderNumber = otu.OrderNumber)

Which gives:

OrderNumber OrderPriority
----------- -------------
1           Low
4           Low

(2 row(s) affected)

Converting that into an UPDATE query gives us this:

UPDATE o
SET o.OrderPriority = 'High'
FROM #Orders o
WHERE EXISTS (
	SELECT NULL
	FROM #OrdersToUpdate otu
	WHERE o.OrderNumber = otu.OrderNumber)

When we run that code the Results window shows that 2 rows were affected and then we can see what we’ve got in the #Orders table:

SELECT *
FROM #Orders

Giving:

OrderNumber OrderPriority
----------- -------------
1           High
2           Low
3           Low
4           High

(4 row(s) affected)
Posted in Microsoft SQL Server | Tagged , , , , , | 1 Comment