(Ebooks PDF) Download SQL Server Analytical Toolkit: Using Windowing, Analytical, Ranking, and Aggregate Functions For Data and Statistical Analysis 1st Edition Angelo Bobak Full Chapters
(Ebooks PDF) Download SQL Server Analytical Toolkit: Using Windowing, Analytical, Ranking, and Aggregate Functions For Data and Statistical Analysis 1st Edition Angelo Bobak Full Chapters
com
OR CLICK BUTTON
DOWLOAD NOW
https://ebookmeta.com/product/sql-server-analytical-toolkit-
using-windowing-analytical-ranking-and-aggregate-functions-for-
data-and-statistical-analysis-1st-edition-angelo-bobak/
https://ebookmeta.com/product/cambridge-igcse-and-o-level-
history-workbook-2c-depth-study-the-united-states-1919-41-2nd-
edition-benjamin-harrison/
https://ebookmeta.com/product/mathematical-analysis-and-
analytical-modeling-1st-edition-ivan-stanimirovic/
https://ebookmeta.com/product/practical-graph-structures-in-sql-
server-and-azure-sql-enabling-deeper-insights-using-highly-
connected-data-1st-edition-louis-davidson-2/
Practical Graph Structures in SQL Server and Azure SQL:
Enabling Deeper Insights Using Highly Connected Data
1st Edition Louis Davidson
https://ebookmeta.com/product/practical-graph-structures-in-sql-
server-and-azure-sql-enabling-deeper-insights-using-highly-
connected-data-1st-edition-louis-davidson/
https://ebookmeta.com/product/fixed-income-mathematics-
analytical-and-statistical-techniques-5th-edition-frank-j-
fabozzi/
https://ebookmeta.com/product/statistical-data-analysis-using-
sas-intermediate-statistical-methods-springer-texts-in-
statistics-marasinghe/
https://ebookmeta.com/product/ground-station-design-and-analysis-
for-leo-satellites-analytical-experimental-and-simulation-
approach-1st-edition-shkelzen-cakaj/
https://ebookmeta.com/product/beyond-advanced-excel-building-
analytical-applications-using-excel-1st-edition-geoffrey-collins/
SQL Server Analytical
Toolkit
Using Windowing, Analytical,
Ranking, and Aggregate Functions
for Data and Statistical Analysis
Angelo Bobak
SQL Server Analytical Toolkit: Using Windowing, Analytical, Ranking, and Aggregate
Functions for Data and Statistical Analysis
Angelo Bobak
Hastings On Hudson, NY, USA
v
Table of Contents
vi
Table of Contents
vii
Table of Contents
viii
Table of Contents
ix
Table of Contents
x
Table of Contents
xiii
Table of Contents
Index������������������������������������������������������������������������������������������������������������������� 1035
xiv
About the Author
Angelo R. Bobak is a published author with more than three
decades of experience and expertise in the areas of business
intelligence, data architecture, data warehouse design, data
modeling, master data management, and data quality using
the Microsoft BI Stack across several industry sectors such as
finance, telecommunications, engineering, publishing, and
automotive.
xv
About the Technical Reviewer
Alicia Moniz is a leader in Data & AI at Microsoft, an
organizer for Global AI Bootcamp – Houston Edition, and
a #KafkaOnAzure Evangelista and prior was a three-time
Microsoft AI MVP. She is an active supporter of women in
technology and volunteers her time at events that help make
AI technology accessible to the masses. She is a co-author of
the Apress publication Beginning Azure Cognitive Services:
Data-Driven Decision Making Through Artificial Intelligence
along with fellow Microsoft MVPs Matt Gordon, Ida Bergum,
Mia Chang, and Ginger Grant. With over 14 years of experience in data warehousing
and advanced analytics, Alicia is constantly upskilling and holds more than 12 in-
demand IT certifications including AWS, Azure, and Kafka. She is active in the Microsoft
User Group community and enjoys speaking on AI, SQL Server, #KafkaOnAzure, and
personal branding for women in technology topics. Currently, she authors the blog
HybridDataLakes.com, a blog focused on cloud data learning resources, and produces
content for the YouTube channel #KafkaOnAzure.
xvii
Introduction
Welcome to my book, SQL Server Analytical Toolkit.
What’s this book about?
This is a book on applying Microsoft SQL Server aggregate, analytical, and ranking
functions across various industries for the purpose of statistical, reporting, analytical,
and historical performance analysis using a series of built-in SQL Server functions
affectionately known as the window functions!
No, not window functions like the ones used in the C# or other Microsoft Windows
application programming. They are called window functions because they implement
windows into the data set generated by a query. These windows allow you to control
where the functions are applied in the data by creating partitions in the query data set.
“What’s a partition?” you might ask. This is a key concept you need to understand to
get the most out of this book. Suppose you have a data set that has six rows for product
category A and six rows for product category B. Each row has a column that stores sales
values that you wish to analyze. The data set can be divided into two sections, one for
each product category. These are the partitions that the window functions use. You can
analyze each partition by applying the window functions (more on this in Chapter 1).
We will see that the window in each partition can be further divided into smaller
windows. The mechanism of a window frame allows you to control which rows in
the partition are submitted to the window function relative to the current row being
processed. For example, apply a function like the SUM() function to the current row being
processed and any prior rows in the partition to calculate running totals by month. Move
to the next row in the partition and it behaves the same.
The book focuses on applying these functions across four key industries: sales,
finance, engineering, and inventory control. I did this so that readers in these industries
can find something they are familiar with in their day-to-day job activities. Even if you
are not working across these industries, you can still benefit by learning the window
functions and seeing how they are applied.
Maybe you want to interview for a developer role in the finance sector? Or maybe
you work in engineering or telecommunications or you are a manufacturer of retail
products. This book will help you acquire some valuable skills that will help you pass the
job interview.
xix
Introduction
Although you could perform these functions with tools like Power BI, performing
these functions at the SQL level precalculates results and improves performance so that
reporting tools use precalculated data.
By the way, there are many books out there on SQL Server and window (or
windowing) functions. What’s so different about this book?
Approach
This book takes a cookbook approach. Not only are you shown how to use the functions,
but you are shown how to apply them across sales, finance, inventory control, and
engineering scenarios.
These functions are grouped into three categories, so for each industry use case we
look at, we will dedicate a chapter to each function category:
• Aggregate functions
• Analytical functions
• Ranking functions
For each function, a query is created and explained. Next, the results are examined
and analyzed.
Where applicable the results are used to generate some interesting graphs with
Microsoft Excel spreadsheets, like creating normal distribution charts for sales data.
Appendix A contains descriptions and syntax for these functions in case you are not
familiar with them, so feel free to examine them before diving into the book.
Key to mastering the concepts in this book is understanding what the OVER() clause
does. Chapter 1 starts off by defining what the OVER() clause is and how it is used with
the window functions.
Several diagrams clearly explain what data sets, partitions, and window frames are
and how they are key to using the window functions.
Each of the industries we identified earlier has three dedicated chapters, one for each
of the window function categories. Each chapter provides a specification for the query to be
written, the code to satisfy the specification, and then one or more figures to show the results.
The book is unique in that it goes beyond just showing how each function works; it
presents use case scenarios related to statistical analysis, data analysis, and BI (BI stands
for business intelligence by the way).
xx
Introduction
The book also makes available all code examples including code to create and load
each of the four databases via the publisher's Google website.
Lastly, just enough theory is included to introduce you to statistical analysis in case
you are not familiar with terms like standard deviation, mean, normal distribution, and
variance. These are important as they will supply you with valuable skills to support your
business users and enhance your skills portfolio. Hey, a little business theory can’t hurt!
Appendix B has a brief primer on statistics, so make sure to check it out in case these
topics are new to you. It discusses standard deviation, variance, normal distribution,
other statistical calculations, and bell curves.
Back to the window functions. These functions generate a lot of numerical data. It’s
great to generate numbers with decimal points but even more interesting to graph them
and understand what they mean. A picture is worth a thousand words. Seeing a graph
that shows sales decreasing month by month is certainly worth looking at and should
raise alarms!
You can also use the Excel spreadsheets to verify your results by using the
spreadsheets’ built-in functions to make sure they match the results of your queries.
Always test your data against a set of results known to be correct (you might just learn
a little bit about Microsoft Excel too!). The spreadsheets used in this book will also be
available on the publisher's Google website.
The book includes tips and discussions that will take you through the process of
learning the SQL Server aggregate, ranking, and analytical functions. These are delivered
in a step-by-step approach so you can easily master the concepts. Data results are
analyzed so that you can understand what the function does and how the windows are
used to analyze the data work.
Expectations
Now that you know what you are in for, what do I expect from you?
Not much really, at a high level.
I expect you to be an intermediate to advanced SQL Server developer or data
architect who needs to learn how to use window functions. You can write medium-
complexity queries that use joins, understand what a CTE (common table expression) is,
and be able to create and load database tables.
You could also be a tech-savvy business analyst who needs to apply sophisticated
data analysis for your business users or clients.
xxi
Introduction
Lastly, you could be a technology manager who wants to understand what your
development team does in their roles as developers. All will benefit from this book.
In conclusion, you need
In case you do not know how to use SSMS, there are many excellent YouTube videos
and sites that can show you how to use this tool in a short amount of time.
You can also check out my podcast “GRUMPY PODCAST 01 NAVIGATING SSMS” at
www.grumpyolditguy.com under the TSQL Podcasts menu selection in the menu bar.
Note You can download the code from the publisher’s Google website at
https://github.com/Apress/SQL-Server-Analytical-Toolkit.
xxii
Introduction
Very simple and easy to read. It is clear by the names used that the query retrieves
departmental information, specifically the department identifier, the manager identifier,
and the manager’s last name. Notice the name of the table. There is no doubt as to what
the table contains.
That’s it! Let’s begin our journey into window functions.
xxiii
CHAPTER 1
1
© Angelo Bobak 2023
A. Bobak, SQL Server Analytical Toolkit, https://doi.org/10.1007/978-1-4842-8667-8_1
Chapter 1 Partitions, Frames, and the OVER( ) Clause
data set can also be a partition by itself, and a window can be defined that uses all rows
in the single partition. It all depends on how you include and define the PARTITION BY,
ORDER BY, and ROWS/RANGE window frame clauses.
These conditions can be specified with the OVER() clause. Let’s see how this works.
• Seven years later, aggregate functions with support for the ORDER BY
clause were introduced in 2012.
• Support for window frames (which we will discuss shortly) was also
introduced in 2012.
2
Chapter 1 Partitions, Frames, and the OVER( ) Clause
The capability of the window functions has grown over the years and delivers a rich
and powerful set of tools to analyze and solve complex data analysis problems.
Each of the subsequent chapters will create and discuss queries for these categories
for four industry-specific databases that are in scope for this book. Please refer to
Appendix A for syntax and descriptions of what each of the preceding functions does if
you are unfamiliar with them or need a refresher on how to use them in a query.
3
Chapter 1 Partitions, Frames, and the OVER( ) Clause
SELECT OrderYear,OrderMonth,SalesAmount,
SUM(SalesAmount) OVER(
PARTITION BY OrderYear
ORDER BY OrderMonth ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS AmountTotal
FROM OverExample
ORDER BY OrderYear,OrderMonth
GO
Between a set of parentheses after the OVER keyword, three other clauses can be
included such as PARTITION BY, ORDER BY, and ROWS or RANGE clauses (to define the
window frame that presents the rows to the function for processing).
Even if you have an ORDER BY clause in the OVER() clause, you can also include the
usual ORDER BY clause at the end of the query to sort the final processed result set in any
order you feel is appropriate to the business requirements the query solves.
Syntax
The following are three basic syntax templates that can be used with the window
functions. Reading these syntax templates is easy. Just keep in mind keywords between
square brackets mean they are optional. The following is the first syntax template
available for the OVER() clause:
Syntax 1
Most of the window functions use this first syntax, and it is composed of three
main clauses, the PARTITION BY clause, the ORDER BY clause, and a ROWS or RANGE
specification. You can include one or more of these clauses or none. These combinations
will affect how the partition is defined. For example, if you do not include a PARTITION
BY clause, the entire data set is considered a one large partition. The expression is usually
one or more columns, but in the case of the PARTITION BY and ORDER BY clauses, it could
also be a subquery (refer to Appendix A).
The Window Function is one of the functions identified in Table 1-1.
This first syntax is pretty much the same for all functions except for the
PERCENTILE_DISC() and PERCENTILE_CONT() functions that use a slight variation:
Syntax 2
These functions are used to calculate the percentile discrete and percentile
continuous values in a data set column. The numeric literal can be a value like .25, .50,
or .75 that is used to specify the percentile you wish to calculate. Notice that the ORDER
BY clause is inserted between the parentheses of the WITHIN GROUP command and the
OVER() clause just includes the PARTITION BY clause.
Don’t worry about what this does for now. Examples will be given that make the
behavior of this code clear. For now, just understand that there are three basic syntax
templates to be aware of.
In our chapter examples, the expression will usually be a column or columns
separated by commas although you can use other data objects like queries. Please
refer to the Microsoft SQL Server documentation to check out the detailed syntax
specification or Appendix A.
Lastly, our third syntax template applies to SQL Server 2022 (release 16.x). The
window capability has been enhanced that allows you to specify window options in a
named window that appears at the end of the query:
Syntax 3
As of this writing, SQL Server 2022 is available for evaluation only. In Listing 1-2 is an
example TSQL query that uses this new feature.
SELECT OrderYear,OrderMonth,SalesAmount,
SUM(SalesAmount) OVER SalesWindow AS SQPRangeUPCR
FROM OverExample
WINDOW SalesWindow AS (
PARTITION BY OrderYear
ORDER BY OrderMonth
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
);
GO
The name of the window is SalesWindow, and it is used right after the OVER operator
instead of the PARTITION BY, ORDER BY, and RANGE clauses as used in the first syntax
template we discussed.
Probably a good feature in case you have multiple window functions in your SELECT
clause that need to use this partition and window frame configuration. This would avoid
repeating the partition code in each column of the SELECT clause.
The PARTITION BY, ORDER BY, and RANGE clauses are declared at the end of the
query between parentheses after the WINDOW keyword instead of right after the OVER
keyword.
If you want to play around with this, download and install the 2022 evaluation
license and try it out on the example code available with the book or on your own
queries. The setup and download are fast and simple. Make sure you get the latest
version of SSMS. These are available on Microsoft’s download website.
A picture is worth a thousand words, so let’s look at one now. Please refer to
Figure 1-1.
Figure 1-1. A simple data set with three partitions and an example frame
Here we have a simple data set composed of eight rows. There are three example
partitions in this data set. One can include all eight rows of the data set; the other two
include rows identified by the TYPE column. There are only two type values, type A and
type B, so each of these partitions will have four rows. By the way, you cannot include
multiple PARTITION BY clauses in an OVER() clause.
You can define only one partition per OVER() clause although you can have more
than one column in the SELECT clause of the query that uses a partition. You can specify
different column combinations to define the partitions.
Where the power of this architecture comes in is that we can create smaller window
frames against the partition by using the ROWS or RANGE operator. These will allow you to
specify how many rows before and/or after the current row being processed will be used
by the window function.
7
Chapter 1 Partitions, Frames, and the OVER( ) Clause
In our preceding example snapshot, the current row is row 3, and the window frame
is defined so it includes only the prior row, the current row, and the next row relative
to the current row. If we apply the SUM() function to this window frame and add all the
values, we get the result 60 (15 + 20 + 25). (Remember this is within the first partition,
which contains only four rows.)
If processing continues on the next row, row 4, only rows 3 and 4 are available to
the SUM() function, and the result is 45 (20 + 25). I neglected to mention that if we start
at row 1, then only rows 1 and 2 are available to the SUM()function because there is no
prior row. The function returns the value 25 (10 + 15).
How do we control this type of processing? All we need to do is add a ROWS or RANGE
specification to the query if required. We could also include an ORDER BY clause to
specify how to order the rows within the partition so that the window function is applied
as needed. For example, generate rolling totals by month, starting of course at month 1
(January) and ending at month 12 (December).
Sounds easy, but we need to be aware of a few scenarios around default processing
when we leave the ORDER BY clause and/or the PARTITION clause out. We will discuss
these shortly.
8
Chapter 1 Partitions, Frames, and the OVER( ) Clause
This clause tells the function to operate on the current row and all rows preceding
the current row if there are any in the partition. A simple diagram in Figure 1-2 makes it
all clear.
Figure 1-2. Include the current row and all preceding rows
If we start at row 1, since there are no prior rows in the partition before this row, the
SUM() function returns the value 10.
Moving on to row 2, the SUM() function will include the only available prior row
(row 1), so the result is 25 (10 + 15).
Next (shown in the preceding figure), the current row to be processed is row 3. The
SUM() function will evaluate row 3 plus rows 1 and 2 in order to generate the total. The
result is 45 (10 + 15 + 20).
Lastly, moving to row 4, the function will include the current row and all prior rows
in its calculation and return 70 (10 + 15 + 20 + 25). Processing now concludes for this
partition.
Moving to partition B, the processing repeats itself, and only rows from partition B
are included. All rows in partition A are ignored.
9
Chapter 1 Partitions, Frames, and the OVER( ) Clause
The first clause is legal but the second is not. It is not supported. One would think
that if there is a ROWS UNBOUNDED PRECEDING, there should be a ROWS UNBOUNDED
FOLLOWING, but it is not supported at this time. Go figure!
As stated earlier, this clause takes us in the opposite direction than the prior scenario
we just discussed. It will allow the aggregate or other window functions to include the
current row and all succeeding rows until all rows in the partition are exhausted. Our
next diagram in Figure 1-3 shows us how this works.
Figure 1-3. Process the current row and all succeeding rows
10
Chapter 1 Partitions, Frames, and the OVER( ) Clause
Next, if the current row being processed is row 2 as in the preceding example, then
the SUM() function will include rows 2–4 to generate the total value. It will generate a
result of 60 (15 + 20 + 25).
Moving on to row 3, it will only include rows 3 and 4 and generate a total value of 45
(20 + 25).
Once processing gets to row 4, only the current row is used as there are no more rows
available in the partition. The SUM() function calculates a total of 25.
When processing resumes at the next partition, the entire scenario is repeated.
What if we do not want to include all prior or following rows but only a few before or
after? The next window frame clause will accomplish the trick for limiting the number of
following rows:
Including this clause in the OVER() clause will allow us to control the number of
rows to include relative to the current row, that is, how many rows after the current row
are going to be used from the available partition rows. Let’s examine another simple
example where we want to include only one row following the current row in the
calculation.
Please refer to Figure 1-4.
11
Chapter 1 Partitions, Frames, and the OVER( ) Clause
Processing starts at row 1. I think by now you understand that only rows 1 and 2 are
used and the result is 25 (10 + 15).
Next, in the preceding example, row 2 is the current row. If only the next row is
included, then the SUM() function will return a total of 35 (15 + 20).
Moving to row 3 (the next current row), the SUM() function will return 45 as the sum
(20 + 25).
Finally, when processing gets to the last row in the partition, then only row 4 is used
and the SUM() function returns 25.
When processing continues to the next partition, the sequence repeats itself ignoring
the values from the prior partition.
We can now see how this process creates windows into the partition that change
as the rows are processed one by one by the window function. Remember, the order
in which the rows are processed is controlled by the ORDER BY clause used in the
OVER() clause.
12
Chapter 1 Partitions, Frames, and the OVER( ) Clause
The next example takes us in the opposite direction. We want to include the current
row and the prior two rows (if there are any) in the calculation.
The window frame clause is
The letter n represents an unsigned integer value specifying the number of rows. The
following example uses 2 as the number of rows.
Please refer to Figure 1-5.
Figure 1-5. Include two prior rows and the current row
Starting at row 1 (the current row), the SUM() function will only use row 1 as there are
no prior rows. The value returned by the window function is 10.
Moving to row 2, there is only one prior row so the SUM() function returns 25
(10 + 15).
13
Chapter 1 Partitions, Frames, and the OVER( ) Clause
Next, the current row is row 3, so the SUM() function uses the two prior rows and
returns a value of 45 (10 + 15 +20).
In the preceding figure, the current row being processed is row 4 and the preceding
two rows are included; the SUM() function when applied will return a total value of 60 (15
+ 20 + 25).
Since all rows of the first partition have been processed, we move to partition B, and
this time only row 5 is used as there are no prior rows. We are at the beginning of the
partition. The SUM() function returns a total value of 30.
Processing continues at row 6, so the SUM function processes rows 5 and 6 (the
current and prior rows). The total value calculated is 65 (30 + 35).
Next, the current row is 7 so the window function will include rows 5, 6, and 7. The
SUM() function returns 105 (30 + 35 + 40).
Finally, processing gets and ends at row 8 of the partition. The rows used by the
SUM() function are rows 6, 7, and 8. The SUM() function() returns 120 (35 + 40 + 45).
There are no more partitions so the processing ends.
What if we want to specify several rows before and after the current row? The next
clause does the trick. This was one of the example in the chapter, but let’s review it again
and make one change:
In this case we want to include the current row, the prior row, and two following
rows. We could well specify two rows preceding and three rows following or any
combination within the number of rows in the partition if we had more rows in the
partition.
Please refer to Figure 1-6.
14
Chapter 1 Partitions, Frames, and the OVER( ) Clause
Starting at row 1 of the partition, the SUM() function can only use rows 1, 2, and 3
as there are no rows in the partition prior to row 1. The result calculated by the SUM()
function is 45 (10 + 15 + 20).
Moving to the next row, row 2 of the partition, the SUM() function can use rows 1, 2
(the current row), 3, and 4. The result calculated by the SUM() function is 70 (10 + 15 +
20 + 25).
Next, the current row is row 3. This window frame uses row 2, 3, and only 4 so the
SUM() function will calculate a total sum of 60 (15 + 20 + 25).
Finally, moving to row 4 (last row of the partition), the SUM() function can only use
rows 3 and 4 as there are no more available rows following in the partition. The result is
45 (20 + 25).
Processing at the next partition continues in the same fashion, ignoring all rows from
the prior partition.
15
Chapter 1 Partitions, Frames, and the OVER( ) Clause
We have pretty much examined most of the configurations for the ROWS clause. Next,
we look at window frames defined by the RANGE clause, which works at a logical level. It
considers values instead of physical row position. Duplicate ORDER BY values will yield a
strange behavior.
16
Chapter 1 Partitions, Frames, and the OVER( ) Clause
When we get to row 3, the first of two duplicate months, the window function (SUM()
in this case) will include all prior rows and add the values in row 3 and the next row 4
to generate a total value of 600.00. This is displayed for both rows 3 and 4. Weird! One
would expect a running total value of 400.00 for row 3.
Let’s try another one. If we apply the following RANGE clause to calculate
running totals
or
we get interesting results. Check out the partial results in Figure 1-7.
Everything works as expected until we get to the duplicate rows with a value of 5
(May) for the month. The window frame for this partition includes rows 1–4 and the
current row 5, but we also have a duplicate month value in row 6, which calculates the
rolling total value 60. This value is displayed in both rows 5 and 6. Aggregations continue
for the rest of the months (not shown).
17
Chapter 1 Partitions, Frames, and the OVER( ) Clause
Let’s process rows in the opposite direction. Here is our next RANGE clause:
By the way, the second RANGE clause is not supported, but I included it so you are
aware that it will not work and generate an error. Please refer to Figure 1-8.
Rows 5 and 6 represent two sales figures for the month of May. Since these are
considered duplicates, row 5 displays a rolling value of 90 and row 6 also shows 90
instead of 80 as one would expect if they did not understand the behavior of this window
frame declaration.
Notice, by the way, how the rolling sum values decrease as the row processing
advances from row 1 onward. We started with 130 and ended with 10 – moving totals in
reverse.
Putting it all together, here is a conceptual view that illustrates the generation of
window frames as rows are processed when the following ROWS clause is used:
18
Chapter 1 Partitions, Frames, and the OVER( ) Clause
This was one of the example in the chapter. Only the partition for type A rows is
considered. Please refer to Figure 1-9.
Both partitions are shown so you can see how the frame resets when it gets to the
next partition.
The generated window frames, as processing goes row by row, show which values
are included for the window function to process within the partition. The first window
and last window only have two rows to process, but the second and third both have three
rows to process, the prior, current, and next rows. The same pattern repeats itself for the
second partition.
Let’s put our knowledge to the test by looking at a simple query based on the figures
we just examined.
Example 1
We will start by creating a small test temporary table for our analysis.
The following listing shows the test table CREATE TABLE DDL (data declaration
language) statement created as a temporary table and one INSERT statement to load all
the rows we wish to process.
19
Chapter 1 Partitions, Frames, and the OVER( ) Clause
20
Chapter 1 Partitions, Frames, and the OVER( ) Clause
(24,2011,8,10),
(25,2011,9,10),
(26,2011,10,10),
(27,2011,11,10),
(28,2011,12,10);
The CREATE statement is used to create a simple table with four columns: a Row
column to identify the row numbers, a Year column and a Month column for the
calendar information, and an Amount column to store a numerical value.
The column names Year and Month are not good names as they are reserved words
in SQL Server, but since this is a simple test table, I did not get too rigorous with naming
standards. Also, I used them in the figures for the RANGE examples, so we are consistent
(at least for our simple examples).
We wish to load two years’ worth of data with some duplicate months so we can see
the difference between how the ROWS clause and the RANGE clause treat these situations.
Here is our first query. Let’s calculate some amount totals by year and month. We go
forward with a RANGE clause that considers the current row and all following rows.
Please refer to the partial listing in Listing 1-4.
SELECT Row,[Year],[Month],Amount,
SUM(Amount) OVER (
PARTITION BY [Year]
ORDER BY [Month]
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS RollingSalesTotal
FROM #TestTable
ORDER BY [Year],[Month] ASC
GO
Notice the square brackets around the Year and Month column names. Using these
will eliminate the colors SSMS uses to display reserved keywords. Leaving them out
won’t hurt, but the colors will be used in the query pane, which makes you aware you are
using reserved keywords. Don’t forget to drop the temporary table.
21
Chapter 1 Partitions, Frames, and the OVER( ) Clause
In Figure 1-10 are the partial results so you can see the entire range of values for
one year.
Looks like the totals are decreasing, which makes sense as we are going forward from
the current row being processed by the window function. Look at the familiar duplicate
behavior in rows 5 and 6 when both months are 5 (May). Both rows have the same value
of 90.00.
22
Chapter 1 Partitions, Frames, and the OVER( ) Clause
When we get to December, in row 13, we have no more rows to process in the
partition, so we only return the value 10.00 for the sum. This is the value for the current
and last row in the partition.
In the second year partition, we have two clusters of duplicate rows, one for
the month of May and one for the month of July. Again, we see the behavior that is
characteristic of the RANGE clause.
By the way, the following window frame clauses are not supported:
These do not work, as the RANGE clause is a logical operation, so specifying a number
for the rows to include in the window frame is not allowed. If you try to use these, you
will get this wonderful error message:
RANGE is only supported with UNBOUNDED and CURRENT ROW window frame
delimiters
Pretty clear, don’t you think?
The last item we need to discuss in this chapter is the default behavior if we do not
include window frame clauses in our OVER() clause. The behavior changes depending
on how you include or not include the ORDER BY and PARTITION BY clauses.
• PARTITION BY clause
• ORDER BY clause
The first three clauses are optional. You can leave them out or include one or more as
required. There are two scenarios to consider when applying (or not) these clauses.
23
Chapter 1 Partitions, Frames, and the OVER( ) Clause
Scenario 1
The default behavior of the window frames is dependent on whether the ORDER BY
clause is included or not. There are two configurations to consider:
If the ORDER BY clause and the PARTITION BY clause are omitted and we do not
include the window frame clause
If the ORDER BY clause is omitted but the PARTITION BY clause is included and we do
not include the window frame clause
The default window frame behavior for both these cases is
Scenario 2
On the other hand, if we include an ORDER BY clause, the following two conditions also
have a default window frame behavior:
If the ORDER BY clause is included but the PARTITION BY clause is omitted and we do
not include the window frame clause
If the ORDER BY clause is included and the PARTITION BY clause is included and we
do not include the window frame clause
The default window frame behavior for both these cases is
Make sure you keep these default behaviors in mind as you start to develop queries
that use the window functions. This is very important; otherwise, you will get some
unexpected and possibly erroneous results. Your users will not be happy (is your resume
up to date?).
Table 1-3 might help you remember these default behaviors.
24
Another Random Document on
Scribd Without Any Related Topics
be casually explained, and of Horton’s hour there remained no other
indication.
The gold! He could revel in it now, feel its solid, reassuring touch,
know that for each separate clinking coin and crackling bill he could
demand of the world full measure in all that he had thought denied to
him forever! He dragged the bag from its hiding place, and dropping
unheedingly into the same chair which Horton had occupied two
hours before, he opened it, working the secret spring as he had seen
the other do. There it all lay before him; the few neat cylinders of
gold, the many compact piles of yellow-backs! He fondled them in a
strange ecstasy of possession, drunk with the knowledge of his own
power. Had a glimpse of his face been vouchsafed him at the
moment, he would not have recognized it as his own, so distorted
was it by the passion which consumed him. Avarice had never laid
its clutching fingers on him before, he had never known the
rapacious hunger for wealth which assailed others; and it was not
now the money itself over which he gloated, but all that it stood for,
all that it would mean to him.
He had known the galling shackles of necessity which bound him
to the wheel of circumstance, and now at one blow he had struck
them off! He was free!
How long he crouched there he never knew, but after a time the
first ecstasy passed and a measure of sanity returned. The money
was his now; but he could not make instant use of his fortune, nor
could he leave it in that bag. The logical thing would be to place it in
the safe built into the wall of his bedroom, of which Potter had shown
him the combination before he departed. The gold and banknotes
would form too bulky a package to be concealed from Homachi’s
sharp eyes anywhere else in the apartment, and Storm repelled the
thought of conveying it secretly to some safe deposit vault. He must
keep it in his immediate possession, within reach of his hand.
He rose and carried the bag into the bedroom where he carefully
counted out its contents upon the bed. One thousand, ten, twenty,
fifty, one hundred, a hundred and twelve! He gasped at the
immensity of it spread out before him! A hundred and twelve
thousand dollars; and there were still some smaller gold coins and a
two-dollar bill! As he lifted the bag something clinked within it, and
investigating an inner pocket he discovered eight shining new dimes
and four bright pennies. Five hundred and fifty-two dollars and
eighty-four cents in addition to the thousands! He recalled Horton’s
statement of the amount, and an ironic smile curved his lips. What a
methodical, cautious, conscientious protector of other people’s
money he had been, and how little it had availed him or them when
the blow fell!
Storm opened the safe, deposited the money within it down to the
last penny, and closing it slid the panel back into place. The bag
remained to be disposed of, and there was Horton’s hat and pistol,
too, in the drawer of the living-room table. He must get rid of them at
the earliest possible moment, and in a manner which could not be
traced. Of course, there was a chance that Horton’s body would not
be discovered until all means of identification had been obliterated;
but it was so unlikely that Storm dismissed it from his thoughts. He
could not afford to gamble on a favorable long shot now; he must
look at this situation as squarely as he had the first desperate one of
a month before, and prepare himself for every contingency.
Horton’s clothing must surely contain papers revealing his identity
and attesting to his connection with the Mid-Eastern coal people. In
the event that his body were found on the morrow, they would be
communicated with, perhaps even before they had time to grow
uneasy over the non-appearance of their paymaster. In a few hours,
twelve at most, that ordinary looking bag might become the most
important and sought-after article in the country, its description down
to the minutest detail spread broadcast in the press.
How could he rid himself of it and of the pistol and hat as well?
Gruesome accounts recurred to his mind of dismembered bodies
having been wrapped in clumsy packages and dropped overboard in
midstream from ferryboats. But something had always gone wrong;
some sharp-eyed passenger had observed the action and marked
the luckless individual for future identification, or the package itself
had been recovered and the murderer traced by some such trivial
detail as the wrapping or string which enclosed it. Clearly that means
was not to be considered; and yet something must be done, and
Storm could conceive of nothing more difficult to destroy than a stout
leather bag. If he could only pack the other damning evidence—the
hat and pistol—into it and ship it somewhere far away or else check
it at some parcel repository——
Why not! The audacity of the thought made him gasp, and yet its
feasibility instantly took hold upon his mind. If he attempted to
express or send it by parcel post he would be compelled to write an
address, and handwriting could be traced; but if he went to one of
the great railroad terminals at the morning rush hour and checked
the bag at the parcel desk he would merely be handed a numbered
paper tag which could be easily destroyed, and in the hurrying crowd
his identity would surely be lost. Better still, he could employ a stolid
porter to check the bag for him, and it would be held for ten days or
more before investigated as unclaimed.
Of course, there was the danger of his being recognized by some
acquaintance in the passing throng of travelers, but it would be a
simple matter to provide himself with a plausible excuse for his
presence there. The bag itself was inconspicuous in appearance—
Horton had seen to that!—and it bore no signs to reveal the purpose
for which it had been used. The more Storm pondered, the more
favorable the idea impressed him. He would have to get out in the
morning without Homachi’s observation and that of the elevator boy,
but it could be managed. For the rest he must trust to luck until he
had finally rid himself of it; it was the only possible solution.
He took the pistol from the table drawer and weighed it
thoughtfully in his hand. It would not make the bag heavy enough to
occasion remark, and yet it must be packed in carefully; the bag
must have the outward appearance of being filled with the ordinary
concomitants of travel. The hat would help, and for the rest paper
would serve——
Then Storm remembered and blessed his valet’s saving
propensity. On an unused upper shelf in the pantry were a pile of old
newspapers, some of them left from the litter of Potter’s departure,
but most of them painstakingly collected and preserved for some
purpose known only to Homachi’s Asiatic mind.
Storm procured a sheaf of them, and was on the point of
wrapping up the pistol to stow it into the bag when on the front page
of the topmost newspaper he saw roughly scrawled in pencil the
characters, “One-A”. It was the number of his apartment—the
newsdealer’s or house superintendent’s guide for the delivery of the
papers—a common practice, as he knew, all over the city, and yet it
might furnish a clue.
Whipping off the outer sheets of each newspaper, he folded them
and replaced them on the kitchen shelf, then crumpled the others
and lined the bag with them, nesting the pistol secure from
movement or jar in their depths. The hat, folded into a wad, came
next, and then more paper until the bag was full. When closed it had
a comfortably bulging appearance, and Storm snapped the secret
spring into place and set it on the floor between the dressing table
and wall where it would escape Homachi’s eyes when he came to
call his master in the morning.
Morning? Already a dim gray effulgence was stealing in between
the curtains of the window, and Storm smiled to himself. How
different was the vigil from the one of a month ago when he had sat
quaking and bathed in sweat upon the foot of his bed, longing for yet
dreading the coming of the dawn, waiting through tortured ages for
the cry to echo up from below which would tell him that the body of
his first victim had been discovered!
Now he knew that he had nothing to fear. He was master of this
situation as he had been of the other, had he but realized it fully
then. He extinguished all the lights except the low wall bracket at the
bed’s head and disrobed lazily, glorying in his steady nerve, his iron
control of himself.
No compunction came to him at the thought of the night’s work.
Jack Horton had played so small a part in his life in the all but
forgotten college days that the reminiscences had awakened no
responsive chord. Hungry as he had been for human companionship
in his despondency, the commonplace, cocksure stranger who spoke
with the easy familiarity of an old friend had bored and slightly
repelled him until he displayed his treasure. Even then he had not
become a personality, but merely a wall of flesh and blood which
stood between Storm and that which became in a twinkling of an eye
imperative to his whole future existence.
How every circumstance had played into his hands! The
remarkable coincidence of their meeting, the need of caution on
Horton’s part which had prevented their taking a taxicab, prevented
the establishment of any clue which would lead to this apartment on
the Drive! From the moment when Horton stepped from the train until
sooner or later his body would be discovered up there among the
bushes above the rail road track which skirted the Hudson, there
would be a blank which the most astute detectives in the world could
not fill in! The bag and its contents would be discovered and
identified in time, of course, but the treasure which it had contained
would never be traced; it would seep out gradually through the vast
market places of the world in exchange for the good things of life!
Horton’s easy surrender to the proffered hospitality, the fortuitous
clearing away of the storm which made that nocturnal stroke
possible, the accident of the rain-soaked hat which had necessitated
a change to headgear that offered no protection from that blow——
all these had contributed miraculously to the result; but had it not
been for Storm’s instant conception of the masterly scheme, his
nerve and cleverness in carrying it out, his foresight in arranging for
every possible contingency, the money would within a few short
hours have been forever beyond his reach! Such chances come to
but few men and then only once in a life-time; yet what man but he
would have had the genius to grasp it!
Remorse? He choked back a laugh that rose in his throat at the
very thought. What did it matter that a clod like Horton had dropped
out of existence? Yet somehow Storm could not quite dispel the
memory of that shrunken, inert figure slumped helplessly against the
wall; he could not quite close his ears to that good-natured voice
prattling of the trust reposed in him, of the love of the girl who was
“aces high”.
Bah! Was he getting squeamish now? One could only rise on the
shoulders of another, and it had been the way of the world through
countless ages that the strong, the ruthless, the resourceful should
triumph! There had been something dog-like about Horton’s
unaffected pleasure at their meeting, his unquestioning acceptance
of the hospitality offered, the gusto with which he relished the
unaccustomed luxuries, his open-hearted affection and
confidence. . . .
Storm thumped his pillow viciously. Dogs had been kicked from
the path before and would be again! There, within reach of his hand
behind the panel lay the price of all that he asked of the future! A
little more of George Holworthy’s puttering solicitude, of Nicholas
Langhorne’s sleek patronage and domineering authority, a week or
two still perhaps of the mask of mourning, the treadmill of the office,
the dodging of hypocritical, unctuous sympathy over Leila’s loss; and
then freedom! Freedom at last and the wide world in which to forget
it all!
Chapter XVII.
Missing
When Homachi, usually as punctual as a time-clock, arrived
twenty minutes late in the morning he found his employer already
risen and attired for the day. His elaborate protestations of apology
were summarily cut short.
“That’s all right, Homachi, only get me some coffee. I’m in a devil
of a hurry this morning.” Storm checked himself. “Er—I cooked a bite
for myself last night and rather messed up things, but I fancy you can
find enough left for breakfast.”
Homachi’s slant eyes widened.
“Any time you want me I stay, sir,” he declared reproachfully. “I
please cook dinner. Unhappy cars no run this morning, sir. I hurry
coffee——”
He slipped away to the kitchen with his noiseless, catlike tread,
and Storm glanced uneasily toward the corner where the bag lay.
Could Homachi have seen it from where he stood in the doorway?
He gulped his coffee hastily when it was prepared, keeping the
valet busy with trivial services lest he enter the bedroom. The man
held his coat for him, presented his hat and stick and then stood
waiting to usher him out. Confound the fellow’s obsequiousness!
Was he waiting purposely to spy upon him? Inwardly fuming, Storm
turned with an assumed start toward the desk in the living-room.
“Forgot those papers!” he muttered for the other’s benefit, adding
carelessly: “Go ahead and clear up the breakfast things, Homachi.
By the way, I shall not be home until late. You may go this afternoon
at the usual hour.”
Homachi bowed and departed while Storm made a pretense of
rummaging through the papers on the desk. How rocky his nerves
were! He must pull himself together, he must be prepared to face the
risk of the next hour.——That fellow was dawdling unconscionably!
Would he ever clear out?
At last Storm heard the sound of running water in the kitchen and
the subdued clatter of dishes. He tiptoed into the bedroom, seized
the bag, and holding it under his coat made for the door.
Luck was with him! The telephone operator sat at the
switchboard with his back squarely turned, and the elevator had
ascended. The way was clear!
Closing the door behind him Storm walked briskly down the hall
and out into the sunshine, swinging the bag casually in plain view. It
seemed to him to be increasing in dimension and weight at every
step, to be growing to colossal size, dragging his arm from its socket!
He had purposely chosen an early rush hour when clerks and shop
people would be hurrying to their work, but he felt that the eyes of
every passer-by were fastened upon him, boring into the burden that
he carried.
Suppose Horton had been followed on the previous night after all
by some emissary of the company whose funds were in his charge?
In spite of the heat of the morning, the thought brought a cold sweat
out upon Storm’s brow. Horton had boasted volubly of the trust
reposed in him; but what if, unknown to him, the company had
placed a guard or checker upon him? Surely it would not be unusual
when a man was carrying sums of such magnitude in cash?
Suppose the watcher had lost sight of him at the terminal the night
before; was Storm running too great a risk by returning to the same
station? If the fellow were hanging about and should recognize the
bag——!
A thousand wild apprehensions flashed through his brain, but he
fought them back resolutely. He must get rid of the bag at once, and
boldness was his best course. Every moment that he retained it in
his possession increased his danger, and he could not trail over the
town with it in broad day. Even now the body might have been
discovered and identified and messages might be humming back
and forth from Pennsylvania to New York raising the alarm for the
bag and its precious contents. He could not hesitate; he must go on!
The subway express train was crowded to the doors with a
heterogeneous mass of the city’s toilers, and Storm wedged himself
on the platform of one of the rearward cars among a group of
laborers and clerks, hoping fervently that he might escape
recognition before he reached his destination. Remembering the
loaded pistol, he guarded the bag as well as he was able from the
jostling throng, his heart in his mouth at every lurch of the speeding
train. He was glad that he had not thought to remove the cartridges,
for he might have left fingerprints in handling the weapon; but his
nervousness increased as he neared his station. Dared he trust a
porter? Suppose the bag were dropped——
“Grand Central!” called the guard, and Storm braced himself. He
must go through with it now; the moment had come.
He made his way out into the vast terminal and mingled with a
crowd of commuters pouring through one of the gates from an
arriving train. His hat, with its decorous mourning band, was pulled
low over his eyes, and he averted his face, fearing every minute to
feel a hand upon his shoulder and hear his name uttered by some
acquaintance; but he passed on unmolested until he found himself
confronted by a red-capped porter.
“Carry yo’ bag, suh? Taxi, suh?”
Storm eyed the dusky, stolid countenance keenly for a moment,
and then made his decision.
“No, I want the bag checked. Take it to the parcel room, will you?”
“It’ll be a dime, suh,” the porter announced, taking over the
burden nonchalantly.
Storm produced the dime and a quarter more.
“Get me the check as quick as you can. I’m in a hurry.”
The porter scurried off, intent on finishing the job and obtaining a
new client, and Storm followed as well as he was able through the
crowd, keeping his eyes upon the bobbing red cap ahead. He saw
the porter worm his way through a queue of people waiting before a
long counter, saw the bag slammed down upon it to be grasped by a
hand from the other side and disappear. A cry of relief surged up
from his heart, and the impulse to turn and flee before the porter
could return with the check almost overmastered him, but he fought
it down. No question must be raised now about the bag; the porter
must have no cause to recall his appearance later.
“Here yo’ is, suh. Want a taxi?”
Storm pocketed the check, shook his head and turning hurried
from the station in the throng which surged out upon the sidewalk
once more. It was done! No link remained to connect him with the
dead paymaster except the money securely locked away in his safe,
and that bit of numbered cardboard in his pocket. His apprehensions
of the early morning fell from him, and he felt as though he were
treading on air. Now he had only to wait until the news came out and
the nine-days wonder over the murder and the missing money had
subsided, and then he could start upon his journey.
On arrival at the Mammoth Trust Building he went at once to a
washroom downstairs and locked himself in. Then, secure from
observation, he took the parcel check from his pocket. It bore the
number “39”, and as he tore it in strips he wondered whether in the
near future those numerals would stare out at him in scare-head type
from the newspapers. Twisting the strips of thin cardboard together,
he touched a match to them and watched them blaze down to a
pinch of smoldering ashes in the hand-basin. He washed these away
carefully, leaving no slightest smudge behind and then hurried out
and up to his office. More ashes! Ashes now of the last menacing bit
of evidence against himself!
A tiresome conference awaited him, and more than once during
its course Storm had to take a fresh grip on himself to keep from
allowing the secret elation within him to show upon his face. What
would they think, what would they do—these smug-faced, pompous,
eminently conventional members of society who surrounded the
table—if they knew what he had done? Two murders in the space of
a few short weeks, two lives wiped out in the very heart of
civilization, and not a question raised against him, not a breath of
suspicion! By God, he was immune, invincible! He could commit any
crime on the calendar and get away with it! There wasn’t a living soul
clever enough to hunt him down! He was the greatest murderer of
the age, the cleverest man in the world!
The madness of exultation had passed when the noon hour
came, but his spirits were still dangerously high. The sedate
luncheon club did not appeal to his mood and he turned into
Peppini’s where he had lunched with Millard only a few days before.
A voice hailed him from the corner table, and Millard himself rose
with extended hand.
“Hello, old chap! I say, if you’re alone won’t you join me?”
To his surprise Storm found himself responding almost jovially.
“If you’ll lunch with me; I see you are just starting. How is
everything out at Greenlea?”
“Fine! We’ve got a new pro. out at the club and he’s running
things in fine shape; but there isn’t much that he can teach us old
boys, eh?” Millard lowered his voice. “I say, you have seen the
papers?”
Storm started. Could it be that already——? Then he checked
himself half angrily. What did Millard know of Horton?
“Papers?” he repeated vaguely.
“Yesterday. The loss of the Alsace. You remember I told you that
Du Chainat, as he called himself, was on board.”
“Oh, that!” Storm laughed loudly, so loudly that Millard stared at
him in surprise. “Odd thing, wasn’t it? Fancy how the people he
swindled must have felt when they read that he had escaped their
clutches!”
Millard looked shocked.
“Terrible thing, I call it,” he said slowly. “It makes a chap believe
that there is such a thing as retributive justice, after all.”
“Bosh!” Storm waved his hand in contempt. “Where is the justice
in the loss of six or seven hundred lives just to drown one rat of a
swindler and sink all his loot with him? It was chance, that’s all. I tell
you, Millard, if a chap is clever enough he can get away with
anything these days.”
“There isn’t any such clever animal!” Millard shook his head. “I tell
you, after what I learned at Headquarters when I went to explain
about my acquaintance with Du Chainat, I wouldn’t like to pull
anything in this town and hope to get away with it. We who live a
normal, well-ordered, conventional existence haven’t the least
conception of their organization down there; it is perfect!”
Storm shrugged skeptically.
“If Du Chainat had been careful enough of the details of his
getaway, I’ll lay you a wager that they would never have discovered
he was on board the Alsace. No organization can be flawless; it is
the individual, one-man system that is perfect, if that man has the
mentality and courage and patience. Given such a man, I’d pit him
against the whole Department any day.”
“You wouldn’t if you knew the inner workings of that department,
their tremendous ramifications——” Millard broke off and added
eagerly: “I say, would you care to run over to Headquarters with me
sometime? I’ll introduce you to a chap there who will show you all
over the shop, and you’ll be dumbfounded, as I was, at the
thoroughness of their methods of investigation. It’s an eye-opener,
Storm! Of course, if you’re not interested——”
“But I am,” Storm said slowly. Millard’s suggestion was at once a
challenge and temptation. The authorities, all unknowing, had
become his natural enemies now. To enter their stronghold
voluntarily, place himself in their hands and have them exploit for his
benefit the very weapons which would be turned against him if they
but dreamed of what he had done! No criminal of the century, of the
ages, would have dared such a move! It would be a test, a secret
test of his own strength, but it would be a triumph! “I am
tremendously interested, Millard. In fact, I’d like nothing better. When
can you arrange it?” Storm decided to make a bold test of himself.
“To-morrow, if you can spare an hour. Excuse me, and I’ll ’phone
my friend there and find out the best time to take you through.” The
other rose. “Funny business for two respectable, suburban golf
enthusiasts like us to be poking our noses into the methods of crime
detection, isn’t it? It is fascinating, though, as you’ll admit.”
While he was gone Storm sat back in his chair, a little smile
playing about his mouth. By to-morrow, Horton’s body might have
been found; by to-morrow, at any rate, the alarm would have been
sent broadcast for him and the money which had been in his charge.
To hear the affair discussed perhaps in his presence by these so-
called experts; to watch the machinery in motion which was
designed to reveal and crush him and to know that not in a thousand
years would it attain its object, to face them all and laugh in his soul!
What a tremendous situation! He would have to guard himself
carefully, more carefully than he had that morning; he had noted
Millard’s look of surprise at his laughter when Du Chainat was
mentioned; but Millard was an egregious ass, anyway, and there had
been no need of restraining his amusement. What did he care about
Du Chainat now? Was he not possessed of more than the latter had
stolen from him, almost as much, in fact, as he had promised? Had
he not gained it in one stroke by his own adroitness and nerve? Gad,
but to-morrow would bring the rarest sport in the world!
“At four o’clock!” Millard bustled back to the table. “My friend is a
high official there and it means open sesame all over the place. He
says there is nothing very big on now since the Du Chainat affair
went to the wall; but you never can tell when a sensational case is
due, you know, and you’ll be interested in the workings of their
system. Won’t you come out to Greenlea afterward with me for
dinner? We can put you up for the night——”
Storm shook his head.
“No thanks, old man. I don’t feel quite up to the old surroundings
just yet.” He did not have to inject the tremor in his tone. In the midst
of his exultant thoughts the mention of Greenlea had brought back a
thrill of the old horror, a sudden vision, clearer than it had come to
him for days, of Leila lying there in the den as he had struck her
down. God, would the memory of it never rest? That other blow
struck in the dark only a few hours before seemed less real, less
vivid, than the image which had been mirrored on his brain for the
month past. Was he never to be free from it?—Never, he assured
himself savagely, until he had cut absolutely adrift from all such as
this blundering fool Millard, who kept dragging the past back and
spreading it before him! Ah, well, the time would be short now . . .
“I understand how you feel, of course, Storm. Forgive me.”
Millard nodded sympathetically. “Later on, perhaps, you’ll run out for
a few days?”
“Perhaps.” The tremor was gone from his tones, and Storm’s face
was inscrutable as he took leave of his garrulous companion after
arranging a meeting for the following day. His thoughts had swerved
back into the old, impatient, maddening channel. How soon could he
get away? How long would it be before Horton’s death was
established and the hue and cry for the lost money subsided?
There was no link connecting him, Norman Storm, with his
classmate of twenty years before. There was no reason why he, his
constitution impaired by grief over the accidental death of his wife,
should not resign from his position at the trust company and go in
search of forgetfulness and health on a long sea voyage since, as far
as the world knew, he had ample means left from his father’s estate.
And yet Storm realized all at once that he could not go! He was
bound even more irrevocably than by the lack of funds which
yesterday had oppressed him to the environs of this latest act of his.
In vain he told himself that it was mere morbid curiosity; that he
didn’t care, it couldn’t matter to him how or when the crime was
discovered. He knew in advance what the result of the investigation
would be and how the furore over the disappearance of the money
would die out in sheer lack of evidence upon which to continue the
search. Morbid or no, there was a secret spell upon him, a secret
fascination which would hold him there until the case had run its
course and been relegated to the limbo of forgotten things.
In lesser degree, the same impatience which had filled him during
that night-long vigil when he waited for the servant’s cry to announce
Leila’s death now assailed him to learn of the discovery of Horton’s
body. He bought the early editions of the afternoon papers and
scanned them eagerly, but they bore no reference to such an
episode. Had the body, in its fall down that steep declivity, been
arrested by the branches of some clump of underbrush, to lie
concealed perhaps until autumn stripped the foliage away? The
thought was unendurable, the prolonged suspense would drive him
mad!
The money, too, began to worry him. Was its hiding place really
secure? What if Homachi had discovered and made away with it? He
tried to concentrate on the routine work of his office, but the effort
was futile, and at four o’clock he closed his desk and hurried home
to his rooms.
Homachi had departed for the day, and Storm pushed back the
panel in the wall and opened the safe with shaking hands. There lay
the neat piles of bills and roulades of gold just as he had placed
them on the previous night; and the sight of them calmed his jangling
nerves like a potent, soothing draught.
As he stood lost in contemplation of them there came a double
ring at the bell, and he cursed softly beneath his breath as he closed
the safe and pushed the panel back into place. That was George
Holworthy’s ring, and George was the last person he cared to see in
his present mood. Perhaps if he did not reply the other would go
away——
But the bell rang again, and resigning himself to the inevitable
Storm opened the door.
“Hello, Norman.” George’s placid face broadened with a smile of
assured welcome. “I stopped in at the trust company for you but they
said you had left early and I was afraid you were ill. You do look
rather seedy.”
“Oh, I’m all right,” Storm answered shortly. “Didn’t sleep very well
last night, that’s all. Come on in.”
“Suppose you come out?” suggested the other. “I’ve borrowed
Abbott’s car and we can run up the road to some quiet little joint for a
bite of dinner; the air will do you good.”
A sense of relief pervaded Storm. He had dreaded the thought of
seeing George seated where Horton had sat last night, smoking the
same cigars and piling up the ashes on the same tray. He assented
readily enough to the plan, and soon they were seated in the little car
with George at the wheel heading up the Drive.
“Where shall it be?” the latter asked. “The manse or Bryan’s or
out on the Post Road?”
Storm did not reply. They were chugging over the viaduct and
around the turn where he and Horton had walked the night before.
They were nearing the top of the incline where the wall sheered
down—was that a crowd collecting there on the path? He strained
his eyes ahead and unconsciously a muttered exclamation arose in
his throat. The next moment they were upon a little group, and he
saw it was composed of a gossipping phalanx of nurse-maids with
baby carriages, lingering in the last, slanting rays of the westering
sun.
He sank back with a sigh, and the little car plodded on.
“What’s the matter with you?” George demanded in good-natured
sarcasm. “Getting deaf, or something? I asked you where you
wanted to go.”
“Eh?—Oh, anywhere,” Storm responded absently. “As long as it
isn’t one of those jazz places. Don’t go too far; I don’t feel like a long
walk home, and you are bound to strip the gears or do some fool
thing.”
“I like that!” the other retorted. “I only did that once to your car
and then Leila——”
He paused, biting his lip, and Storm clenched his hands. He
could have turned and struck the man beside him!—Leila! Greenlea!
Damn them all, would they never allow him to forget, even for a
moment? Wasn’t there enough on his mind—with that body lying
somewhere back there undiscovered and the thought of the alarm
which must be even now manifesting itself out at the Mid-Eastern
plant in the Alleghanies—without recalling that first hideous affair?
“I—I’ve learned to drive all right now,” George amended hastily.
“Wait till we get up to the road where I can let her out and you’ll see!”
The drive thereafter was a silent one. George, dismayed by his
blundering touch upon his friend’s supposed grief, felt contrite and
self-conscious, and Storm was buried in his own thoughts. What
would George say when he read in the papers of Horton’s
disappearance? The two men had not been over congenial at
college, for George had disapproved of the other’s wild pranks, but
there had been a certain camaraderie between them. Storm felt an
almost irresistible impulse to speak Horton’s name, to hear George
talk of him. It was madness, he knew; the fellow had not been
mentioned between them for years, and if he were to do so now the
coincidence, in the face of the news which must soon come, would
strike even George’s dull perceptions. Yet as they drew up at a cosy
little inn and settled themselves before a table on the vine-screened
veranda, the desire persisted, dominating all other thoughts.
Wholly innocent of subtleties as he was, it seemed as though
George himself had some divination of his companion’s mental
trend, for as he glanced about him he remarked:
“This is like old times, isn’t it? Away back, I mean. Doesn’t this
put you in mind of that little place outside Elmhaven where we used
to drive for those wonderful shore dinners in our college days?”
Storm started almost guiltily, but George chattered on:
“What was the name of it?—Oh, Bailey’s! You remember it, don’t
you, Norman?”
“Of course,” Storm responded cautiously. “We had some great
old times there, didn’t we?”
“Rather.” A reminiscent glow came in to George’s faded blue
eyes. “Pretty good crowd, too. I wonder what has become of them
all?”
Storm’s hand trembled as he started to raise his glass to his lips,
and he set it down hastily. Horton had uttered those same words
only the night before! With an effort he collected himself and
steadied his voice.
“Let’s see,” he began deliberately. “There were Swain and
McKnight and Van Tries and you and I——”
He paused and George nodded.
“Swain and McKnight are gone, but you’re forgetting Caldwell
and Horton. I haven’t heard of either of them in years, have you?”
Storm shook his head, unable to frame a word. In a quick
revulsion of feeling, he wished fervently that he might change the
subject, but his dry lips refused their office.
“Jack Horton was a wild fellow, but there was no real harm in
him,” George pursued. “Just the irresponsibility of youth, I guess.
He’s probably settled down somewhere now and making good.”
Storm gritted his teeth. ‘Making good’! He could have laughed
aloud at the irony of it. God! if he could only silence George before
his self-control broke down!
“You can’t tell what a man will be in twenty years’ time.” Was that
his own voice speaking so coolly, so casually? “Our old crowd has
scattered all over the face of the globe.—Let’s order; I’m starved.”
The talk drifted off to other topics, to his unutterable relief, but
contrary to his assertion Storm scarcely touched the food which was
placed before him. He hoped that George would take a different
route home, but shrank from suggesting it and instead lapsed into a
morose silence. As they passed again that ominous spot upon which
his thoughts centered, he strove to pierce the darkness, but the path
was deserted and no sound came to his ears but the humming of the
motor.
Sleep did not come to him until nearly dawn and he was
awakened from a troubled dream by the sharp, insistent ring of the
telephone.
Springing up to reply, he heard George’s excited tones over the
wire, and the words themselves drove all the haze of nightmare from
his mind.
“Say, have you seen the papers yet? I didn’t mean to wake you
up, but this is the damnedest thing! One of the very fellows we were
talking about last night—Jack Horton—is spread all over the front
page. He has been employed of late years as paymaster for the Mid-
Eastern Coal Corporation, and he is missing with a hundred
thousand dollars!”
Chapter XVIII.
The Girl in the Watch Case
Storm received the news with outward composure, feigning a
natural irritation at being aroused from sleep to mask the chaos of
his thoughts, and cut George off as soon as he was able to stem the
tide of his volubility. Then, throwing a bathrobe about his shoulders,
he stumbled to the hall door and opened it. His own morning paper
lay on the mat, and even before he picked it up the staring headlines
met his eye.
“$112,000 Missing. Trusted Employee Of Mid-Eastern
Disappears With Huge Sum In Cash”.
He shut the door and sinking into the nearest chair read on
absorbedly:
“John M. Horton, pay clerk for the Mid-Eastern Consolidated Coal
Corporation, disappeared on the sixth inst. with a black leather
handbag in his possession containing the total sum of $112,552.84
which he had just drawn from the Mid-Eastern Trust Company’s
Poughkeepsie branch. He was last seen boarding a train in the latter
city at four-forty P. M. for New York en route to Altoona, Pa., and the
alarm was not sent out until late yesterday afternoon.
Representatives of the Mid-Eastern C. C. C. who have been
interviewed loyally declare their faith in the missing man and assert
that he must have met with foul play. When last seen ‘Jack’ Horton,
as he is known, wore a dark green felt hat, black overcoat, blue
serge suit and low tan shoes. He is about forty years of age——”
Storm’s eyes traveled on to the last line of the personal
description and the few meager details added, and the paper
dropped from his listless fingers. This was a contingency which he
had not forseen. He had taken it for granted that the body would be
discovered and identified before the Mid-Eastern people would have
time to take alarm and send out tracers after the missing man.
To his mind in its warped state came no reminder of his own
treachery, no thought of the hospitality betrayed, the blow struck in
the dark from behind. He felt no animosity toward Horton; he had
killed him because the latter stood between him and the money he
coveted. It had been a necessary, even a brilliant stroke, and he felt
no remorse for the dead.
But suppose Horton’s body were not found? An aspersion of theft
might logically follow in the course of time, but it could not harm him
now, and that solution would end any local search. It might be as
well, after all . . .
As he dressed a vague desire came over him to revisit the scene
of that sudden, crafty blow. It could do no harm to stroll up along that
path and just glance over the wall. No suspicion could be attached to
him for that if the body were found later, and he longed to see for
himself if no trace of it could be discerned from above.
Then he thrust that trend of thought from him in a wave of horror.
Great heavens, was he going mad? Murderers had been known to
haunt the scenes of their crimes; that was the way in which they
were frequently caught! He must avoid that spot as he would the
plague! Yet the vague, terrifying sensation of being drawn toward it
persisted, and in sheer desperation he fled downtown earlier than
was his wont and plunged feverishly into the business of the day. It
had a steadying effect upon his nerves, and when noon came he
had quite recovered command of himself.
George telephoned again, asking him to lunch, but he pleaded
another engagement. If he had to listen to old George’s theories and
speculations it would madden him, and he wanted to have himself
well in hand for his visit to Police Headquarters with Millard.
As the hour drew near his keen anticipation mounted. Millard had
said that there was nothing very big on, but that was yesterday; the
disappearance of a man with a hundred thousand dollars in his
possession would be a sensation even in the manifold events of so
huge a city, and he was eager to hear what view had been taken of
the case by the authorities. As on the previous afternoon, he
purchased the earliest editions of the evening papers; but although