Compare commits

...

10 Commits

Author SHA1 Message Date
anthonydb
17b9df5450 Errata update on Ch. 19 listing 2025-02-19 18:51:31 -05:00
anthonydb
98feb63296 Fix small typo in Try It Yourself text 2025-02-18 05:48:18 -05:00
anthonydb
5d8a060610 FAQ updates on pgAdmin 9.0 2025-02-05 19:40:50 -05:00
anthonydb
f8f394190a FAQ and README updates 2024-12-30 07:17:15 -05:00
anthonydb
2f660ae98d FAQ update on Language Pack (Windows) 2024-11-10 19:12:42 -05:00
anthonydb
e9a117c085 Minor formatting update 2024-09-07 21:53:30 -04:00
anthonydb
5b2032536b Minor formatting update 2024-09-07 11:49:57 -04:00
anthonydb
41a9bb7eae Listing 16-19 caption fix 2024-08-05 12:40:45 -04:00
anthonydb
712cec0d31 Updated answer to Try It Yourself Ch. 14, problem 2 2024-07-15 07:23:41 -04:00
anthonydb
b35f9dff17 Additional FAQ/errata updates 2024-06-22 16:48:44 -04:00
8 changed files with 47 additions and 32 deletions

View File

@ -64,7 +64,7 @@ VALUES
SELECT * FROM date_time_types; SELECT * FROM date_time_types;
-- Listing 4-5: Using the interval data type -- Listing 4-5: Using the interval data type
-- Assumes script 4-4 has been run -- (Assumes Listing 4-4 has been run)
SELECT SELECT
timestamp_column, timestamp_column,

View File

@ -212,9 +212,7 @@ ORDER BY id;
SELECT '2020' AS year, SELECT '2020' AS year,
school_2020 AS school school_2020 AS school
FROM district_2020 FROM district_2020
UNION ALL UNION ALL
SELECT '2035' AS year, SELECT '2035' AS year,
school_2035 school_2035
FROM district_2035 FROM district_2035

View File

@ -201,12 +201,10 @@ WITH
(SELECT state_name, sum(pop_est_2018) (SELECT state_name, sum(pop_est_2018)
FROM us_counties_pop_est_2019 FROM us_counties_pop_est_2019
GROUP BY state_name), GROUP BY state_name),
establishments (st, establishment_count) AS establishments (st, establishment_count) AS
(SELECT st, sum(establishments) AS establishment_count (SELECT st, sum(establishments) AS establishment_count
FROM cbp_naics_72_establishments FROM cbp_naics_72_establishments
GROUP BY st) GROUP BY st)
SELECT counties.st, SELECT counties.st,
pop_est_2018, pop_est_2018,
establishment_count, establishment_count,
@ -223,7 +221,6 @@ WITH us_median AS
(SELECT percentile_cont(.5) (SELECT percentile_cont(.5)
WITHIN GROUP (ORDER BY pop_est_2019) AS us_median_pop WITHIN GROUP (ORDER BY pop_est_2019) AS us_median_pop
FROM us_counties_pop_est_2019) FROM us_counties_pop_est_2019)
SELECT county_name, SELECT county_name,
state_name AS st, state_name AS st,
pop_est_2019, pop_est_2019,
@ -266,12 +263,10 @@ FROM crosstab('SELECT office,
FROM ice_cream_survey FROM ice_cream_survey
GROUP BY office, flavor GROUP BY office, flavor
ORDER BY office', ORDER BY office',
'SELECT flavor 'SELECT flavor
FROM ice_cream_survey FROM ice_cream_survey
GROUP BY flavor GROUP BY flavor
ORDER BY flavor') ORDER BY flavor')
AS (office text, AS (office text,
chocolate bigint, chocolate bigint,
strawberry bigint, strawberry bigint,
@ -303,10 +298,8 @@ FROM crosstab('SELECT
GROUP BY station_name, GROUP BY station_name,
date_part(''month'', observation_date) date_part(''month'', observation_date)
ORDER BY station_name', ORDER BY station_name',
'SELECT month 'SELECT month
FROM generate_series(1,12) month') FROM generate_series(1,12) month')
AS (station text, AS (station text,
jan numeric(3,0), jan numeric(3,0),
feb numeric(3,0), feb numeric(3,0),
@ -349,7 +342,6 @@ WITH temps_collapsed (station_name, max_temperature_group) AS
ELSE 'No reading' ELSE 'No reading'
END END
FROM temperature_readings) FROM temperature_readings)
SELECT station_name, max_temperature_group, count(*) SELECT station_name, max_temperature_group, count(*)
FROM temps_collapsed FROM temps_collapsed
GROUP BY station_name, max_temperature_group GROUP BY station_name, max_temperature_group

View File

@ -189,7 +189,6 @@ SET date_1 =
(regexp_match(original_text, '\/\d{2}\n(\d{4})'))[1] (regexp_match(original_text, '\/\d{2}\n(\d{4})'))[1]
||' US/Eastern' ||' US/Eastern'
)::timestamptz, )::timestamptz,
date_2 = date_2 =
CASE CASE
-- if there is no second date but there is a second hour -- if there is no second date but there is a second hour
@ -201,7 +200,6 @@ SET date_1 =
(regexp_match(original_text, '\/\d{2}\n\d{4}-(\d{4})'))[1] (regexp_match(original_text, '\/\d{2}\n\d{4}-(\d{4})'))[1]
||' US/Eastern' ||' US/Eastern'
)::timestamptz )::timestamptz
-- if there is both a second date and second hour -- if there is both a second date and second hour
WHEN (SELECT regexp_match(original_text, '-(\d{1,2}\/\d{1,2}\/\d{2})') IS NOT NULL) WHEN (SELECT regexp_match(original_text, '-(\d{1,2}\/\d{1,2}\/\d{2})') IS NOT NULL)
AND (SELECT regexp_match(original_text, '\/\d{2}\n\d{4}-(\d{4})') IS NOT NULL) AND (SELECT regexp_match(original_text, '\/\d{2}\n\d{4}-(\d{4})') IS NOT NULL)

View File

@ -293,7 +293,7 @@ SELECT ST_SetSRID(
FROM earthquakes FROM earthquakes
ORDER BY id; ORDER BY id;
-- Listing 16-19: Converting JSON coordinates to a PostGIS geometry column -- Listing 16-19: Converting JSON coordinates to a PostGIS geography column
-- Add a column of the geography data type -- Add a column of the geography data type
ALTER TABLE earthquakes ADD COLUMN earthquake_point geography(POINT, 4326); ALTER TABLE earthquakes ADD COLUMN earthquake_point geography(POINT, 4326);

View File

@ -4,8 +4,13 @@
[Practical SQL, 2nd Edition](https://nostarch.com/practical-sql-2nd-edition/) is a beginner-friendly guide to the database programming language SQL. Author [Anthony DeBarros](https://www.anthonydebarros.com) starts with beginner SQL concepts such as queries, data types, and basic math and aggregation, and then works through intermediate and advanced topics including statistics, cleaning data, GIS, and automating tasks. Along the way, you'll use real-world data from the U.S. Census and other government agencies and learn the fundamentals of good database design. This is a book not only about SQL but about best practices for using it for thorough, accurate data analysis. [Practical SQL, 2nd Edition](https://nostarch.com/practical-sql-2nd-edition/) is a beginner-friendly guide to the database programming language SQL. Author [Anthony DeBarros](https://www.anthonydebarros.com) starts with beginner SQL concepts such as queries, data types, and basic math and aggregation, and then works through intermediate and advanced topics including statistics, cleaning data, GIS, and automating tasks. Along the way, you'll use real-world data from the U.S. Census and other government agencies and learn the fundamentals of good database design. This is a book not only about SQL but about best practices for using it for thorough, accurate data analysis.
## A Note About Editions ## A Note About Editions
If you're reading the first edition of the book, published in 2018, please [use the code and data in the first edition repository](https://github.com/anthonydb/practical-sql/). If the cover of your copy does not say, "2nd Edition," then you're using the first edition. If you're reading the first edition of the book, published in 2018, please [use the code and data in the first edition repository](https://github.com/anthonydb/practical-sql/). If the cover of your copy does not say, "2nd Edition," then you're using the first edition.
## Important Updates to pgAdmin
In the book, we write SQL queries and manage our PostgreSQL databases with [pgAdmin](https://pgadmin.org), a free and open source graphical user interface. pgAdmin is under continuous development, and its current interface may differ from the screenshots and instructions in the book. Please check [the book FAQ](https://github.com/anthonydb/practical-sql-2/blob/master/faq-updates-errata.md) for updates.
## Who Is This Book For? ## Who Is This Book For?
Practical SQL is ideal for beginners as well as those who know some SQL and want to go deeper. Practical SQL is ideal for beginners as well as those who know some SQL and want to go deeper.

View File

@ -458,7 +458,7 @@ CREATE TABLE songs (
-- We could consider the catalog_code. We would have to answer yes to -- We could consider the catalog_code. We would have to answer yes to
-- these questions: -- these questions:
-- 1. Is it going to be unique across all albums released by all companies? -- 1. Is it going to be unique across all albums released by all companies?
-- 2. Will an album always have a catelog code? -- 2. Will an album always have a catalog code?
-- 3. To speed up queries, which columns are good candidates for indexes? -- 3. To speed up queries, which columns are good candidates for indexes?
@ -899,26 +899,27 @@ SELECT (regexp_match('Williams, Sr.', '.*, (.*)'))[1];
-- regexp_split_to_table() in a subquery to create a table of words to count. -- regexp_split_to_table() in a subquery to create a table of words to count.
-- Bonus: remove commas and periods at the end of each word. -- Bonus: remove commas and periods at the end of each word.
-- Answer:
-- This query uses a Common Table Expression to first separate each word -- This query uses a Common Table Expression to first separate each word
-- in the text into a separate row in a table named word_list. Then the SELECT -- in the text into a separate row in a table named word_list. As part of the
-- statement counts the words, which are cleaned up with two operations. First, -- operation, we use nested replace functions to remove commas, periods, and
-- several nested replace functions remove commas, periods, and colons. Second, -- colons. Then the SELECT statement counts the words, which we convert
-- all words are converted to lowercase so that when we count we group words -- to lowercase so that when we count we group words that may appear with
-- that may appear with various cases (e.g., "Military" and "military"). -- various cases (e.g., "Military" and "military").
-- Thanks to reader @DavidSwagger for pointing out the replace function
-- needed to happen in the WITH statement.
WITH WITH
word_list (word) word_list (word)
AS AS
( (
SELECT regexp_split_to_table(speech_text, '\s') AS word SELECT regexp_split_to_table(
replace(replace(replace(speech_text, ',', ''), '.', ''), ':', ''),
'\s') AS word
FROM president_speeches FROM president_speeches
WHERE speech_date = '1946-01-21' WHERE speech_date = '1946-01-21'
) )
SELECT lower(word) AS cleaned_word,
SELECT lower(
replace(replace(replace(word, ',', ''), '.', ''), ':', '')
) AS cleaned_word,
count(*) count(*)
FROM word_list FROM word_list
WHERE length(word) >= 5 WHERE length(word) >= 5

View File

@ -2,9 +2,21 @@
### FAQ, Updates, and Errata ### FAQ, Updates, and Errata
This page contains answers to Frequently Asked Questions, updates to material and URLs, and errata for Practical SQL, 2nd Edition. Some of these apply to the first couple of printings of the book and may be updated if you have a third printing or later. Check the copyright page to see which printing you have. This page contains answers to Frequently Asked Questions, updates to material and URLs, and errata for Practical SQL, 2nd Edition. Some only apply to the first printings of the book and have been subsequently incorporated in later printings. Check the copyright page to see which printing you have.
### Important pgAdmin 4 Version 9 Update!
Version 9 of pgAdmin 4, released in February 2025, introduces a new default "workspace" layout that is substantially different from the layout of the tool shown in the book. It's also, in my opinion, less intuitive. Fortunately, it's possible to set the app's layout to the "classic" design shown in the book. To do that:
1. Launch pgAdmin
2. On macOS, select the `pgAdmin` menu, then `Settings`. On Windows, select the `File` menu, then `Preferences`.
3. In the Preferences dialog, navigate to `Miscellaneous` and click `User interface`.
4. Under `Layout`, choose `Classic`. You can also choose a light or dark theme here.
5. Click `Save`.
Please see additional pgAdmin updates in the chapter sections below.
### Introduction ### Introduction
* No updates * No updates
@ -18,11 +30,15 @@ This page contains answers to Frequently Asked Questions, updates to material an
* **Page 5: Windows Installation (PostGIS)** * **Page 5: Windows Installation (PostGIS)**
> The EDB installer for Windows no longer includes the Language Pack. See [this issue](https://github.com/anthonydb/practical-sql-2/issues/32) for details on how to configure Python support.
> The PostGIS installer for Windows now asks you to check off which components to install rather than providing individual Yes/No prompts. You can select all components including Create Spatial Database. (Applies to printings one through three of the book.) > The PostGIS installer for Windows now asks you to check off which components to install rather than providing individual Yes/No prompts. You can select all components including Create Spatial Database. (Applies to printings one through three of the book.)
> The Windows 11 Start menu continues to evolve. To see the PostgreSQL and PostGIS folders added during installation, you may need to click `Start` > `All apps`.
* **Pages 6 and 7: Configuring Python language support (Windows)** * **Pages 6 and 7: Configuring Python language support (Windows)**
> Note that the current version of the EDB Language Pack is updated from the version shown in the book. Use the folder and version name provided via the EDB Windows installer for `PATH` and `PYTHONHOME`. As of October 2023, that is `C:\edb\languagepack\v4\Python-3.11` > The EDB installer for Windows no longer includes the Language Pack. Please see [this issue](https://github.com/anthonydb/practical-sql-2/issues/32) for instructions on how to configure Python support.
* **Pages 12 and on: pgAdmin Renamed "Browser" to "Object Explorer"** * **Pages 12 and on: pgAdmin Renamed "Browser" to "Object Explorer"**
@ -34,15 +50,18 @@ This page contains answers to Frequently Asked Questions, updates to material an
* **Page 14: pgAdmin: Running a Query** * **Page 14: pgAdmin: Running a Query**
> pgAdmin, as of version 8.7 (May 2024), has added new options for running a SQL statement in the Query Tool. Previously, pgAdmin had a single `Execute/Refresh` button in its menu bar. Those have been replaced by two buttons: `Execute Script` and `Execute Query`. > pgAdmin, as of version 8.7 (May 2024), has added new options for running a SQL statement in the Query Tool. Previously, the Query Tool had a single `Execute/Refresh` button in its menu bar. That has been replaced by two buttons: `Execute Script` and `Execute Query`.
> Clicking `Execute Script` will run every statement in your Query Tool editor. Clicking `Execute Query` will run the statement where your cursor is positioned. It also will present you with a dialog box to confirm your choice (which you can choose to silence in the future). Applies to printings one through three of the book.) > Clicking `Execute Script` will run every statement in your Query Tool editor (unless you highlight a statement). Clicking `Execute Query` will run only the statement where your cursor is positioned, without a need to highlight the statement. It also will present you with a dialog box to confirm your choice (which you can choose to silence in the future). Applies to printings one through three of the book.
* **Page 15, Figure 1-5: pgAdmin Query Tool** * **Page 15, Figure 1-5: pgAdmin Query Tool**
> Version 6.9 of pgAdmin, released in May 2022, introduced a redesigned Query Tool Layout. General functionality is the same, but if you are using version 6.9 or later, you will see that some menu icons shown in the book at the top of the window are now placed atop the results grid. (Applies only to first printing of the book.) > Version 6.9 of pgAdmin, released in May 2022, introduced a redesigned Query Tool Layout. General functionality is the same, but if you are using version 6.9 or later, you will see that some menu icons shown in the book at the top of the window are now placed atop the results grid. (Applies only to first printing of the book.)
> Version 8.7 of pgAdmin, released in May 2024, updated how queries are executed in the Query Tool. * **Page 15, Customizing pgAdmin**
> The book states that pgAdmin preferences are accessed by clicking `File` > `Preferences`. This is true for Windows 11. On macOS, click `pgAdmin` > `Preferences`.
### Chapter 2: Creating Your First Database and Table ### Chapter 2: Creating Your First Database and Table
@ -150,7 +169,9 @@ SET datestyle to "ISO, MDY";
### Chapter 19: Maintaining Your Database ### Chapter 19: Maintaining Your Database
* No updates * **Page 392: Listing number**
> In the first paragraph on the page, the sentence should read, "You can confirm this by rerunning the code in Listing 19-2, which shows the table remains at 35MB even after the automatic vacuum."
### Index ### Index