{"id":28496271,"url":"https://github.com/nathanaelmutua/postgresql-notes","last_synced_at":"2025-07-02T20:32:06.539Z","repository":{"id":297085656,"uuid":"995215104","full_name":"NathanaelMutua/PostgreSQL-notes","owner":"NathanaelMutua","description":"A walkthrough of PostrgeSQL","archived":false,"fork":false,"pushed_at":"2025-06-04T19:23:14.000Z","size":252,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-06-04T23:26:56.711Z","etag":null,"topics":["pgadmin4","postgresql","sql","tutorial-code"],"latest_commit_sha":null,"homepage":"https://nathanaelmutua.github.io/PostgreSQL-notes/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NathanaelMutua.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-03T06:27:00.000Z","updated_at":"2025-06-04T19:23:16.000Z","dependencies_parsed_at":"2025-06-04T23:27:00.846Z","dependency_job_id":null,"html_url":"https://github.com/NathanaelMutua/PostgreSQL-notes","commit_stats":null,"previous_names":["nathanaelmutua/my-programming-notes","nathanaelmutua/postgresql-notes"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/NathanaelMutua/PostgreSQL-notes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NathanaelMutua%2FPostgreSQL-notes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NathanaelMutua%2FPostgreSQL-notes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NathanaelMutua%2FPostgreSQL-notes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NathanaelMutua%2FPostgreSQL-notes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NathanaelMutua","download_url":"https://codeload.github.com/NathanaelMutua/PostgreSQL-notes/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NathanaelMutua%2FPostgreSQL-notes/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263210343,"owners_count":23431104,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pgadmin4","postgresql","sql","tutorial-code"],"created_at":"2025-06-08T12:07:04.530Z","updated_at":"2025-07-02T20:32:06.531Z","avatar_url":"https://github.com/NathanaelMutua.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 style=\"text-align: center; padding: 40px 2px\"\u003eQuerying Data in PostgreSQL\u003c/h1\u003e\n\u003cp style=\"text-align: center; font-style: italic;\"\u003eLearning SELECT, Aliases, ORDER BY, and DISTINCT with Lucy, Nathanael and Stella\u003c/p\u003e\n\n\n\u003ch2 style=\"text-align: center; padding-top: 100px\"\u003eTable of Contents\u003c/h2\u003e\n\n  1. [Introduction](#introduction)\n  2. [Setup](#setup)\n  3. [The Select Statement](#the-select-statement)\n  4. [Column Aliases](#column-aliases)\n  5. [ORDER BY Clause](#order-by-clause)\n  6. [SELECT DISTINCT Clause](#select-distinct)\n  7. [Querying Tips](#querying-tips)\n  8. [PostgreSQL Querying Summary](#postgresql-querying-summary)\n\n\u003ch2 style=\"padding-top: 100px\" id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\n### Creating the 'sample_t2g' database...just to work in\nFirst, open the Command Prompt on Windows or Terminal on Unix-like systems and connect to the PostgreSQL server using psql tool:\n\n```\npsql -U postgres\n```\n\nIt’ll prompt you to enter a password for the postgres user:\n\n```\nPassword for user postgres:\n```\n\nAfter entering the password correctly, you will be connected to the PostgreSQL server.\n\nThe command prompt will look like this:\n```\npostgres=#\n```\n\nSecond, create a new database called sample_t2g using CREATE DATABASE statement:\n```\nCREATE DATABASE sample_t2g;\n```\n\nOutput:\n```\nCREATE DATABASE\n```\n\nPostgreSQL will create a new database called sample_t2g.\n\nThird, verify the database creation using the \\l command. The \\l command will show all databases in the PostgreSQL server:\n\n```\n\\l\n```\n\nNext, switch the current database to sample_t2g:\n```\n\\c sample_t2g\n```\nThe command prompt will change to the following:\n```\nsample_t2g=#\n```\n\nNow let's start...\nWe will cover essential querying techniques using the `employees` table:\n\n```sql\nCREATE TABLE employees (\n  id SERIAL PRIMARY KEY,\n  first_name VARCHAR(50),\n  last_name VARCHAR(50),\n  department VARCHAR(50),\n  hire_date DATE,\n  salary NUMERIC(10,2),\n  email VARCHAR(100)\n);\n\nINSERT INTO employees VALUES\n(1, 'Stella', 'Stephanie', 'Engineering', '2023-01-15', 89000, 's.stephanie@company.com'),\n(2, 'Nathanael', 'Mutua', 'Marketing', '2022-03-22', 90000, 'nathanael.m@company.com'),\n(3, 'Lucy', 'Wanjiru', 'Director', '2023-11-05', 92000, 'l.wanjiru@company.com'),\n(4, 'Mwangi', 'Johnson', 'HR', '2021-08-30', 68000, 'mwangij@company.com'),\n(5, 'Daniel', 'Njoroge', 'Engineering', '2023-01-15', 85000, 'dan.njoro@company.com'),\n(6, 'Anna', 'Kiptoo', NULL, '2023-05-01', 75000, 'anna.kip@company.com'),\n(7, 'Wilson', 'Kiptoo', 'Engineering', '2024-02-12', 85000, 'wilson.kip@company.com'),\n(8, 'Mercy', 'Mumo', 'Marketing', '2024-02-12', 42000, 'mercy.mumo@company.com'),\n(9, 'Michael', 'Kiptoo', NULL, '2023-07-01', 65000, 'anna.kip@company.com'),\n(10, 'Johnson', 'Kiptoo', 'HR', '2025-03-01', 68000, 'johnson.kip@company.com');\n```\n\n\n\u003ch2 style=\"padding-top: 60px\" id=\"setup\"\u003eSetup\u003c/h2\u003e\n\n### Requirements\n- Have PostgreSQL installed..[click here for a tutorial](https://www.youtube.com/watch?v=GpqJzWCcQXY)\n- Have PGADmin 4 installed...[click here for a tutorial](https://www.youtube.com/watch?v=4qH-7w5LZsA)\n- Create a database (you can name it as you wish)\n\n\u003cimg src=\"./images/create-database.png\" alt=\"Creating Database\" width=\"350\" \u003e\n\n- Now we can start, just open the query tool:\n\n\u003cimg src=\"./images/access-query.png\" alt=\"Accessing Query Tool\" width=\"350\" \u003e\n\n- Create the employees table above, then let's jump right in.\n\n\u003ch2 style=\"padding-top: 100px\" id=\"the-select-statement\"\u003e1. The SELECT Statement\u003c/h2\u003e\n\n### What I will cover:\n- [Basic Syntax](#basic-syntax)\n- [Fetching Specific Columns](#fetch-specific-columns)\n- [Selecting Multiple columns](#selecting-multiple-columns)\n- [Fetching all columns](#fetch-all-columns)\n- [Using Expressions](#using-expressions)\n\nIt is like the foundation of data retrieval in PostgreSQL.\n\nIt is a command for retrieving data from tables within a PostgreSQL database. It enables users to specify which columns to fetch and apply filters for targeted results.\n\n### Basic Syntax\n```sql\nSELECT column1, column2, ...\nFROM table_name;\n```\n\n### Key Examples\n### Fetch specific columns\nWe specify the columns to be selected after the 'SELECT' keyword.\n\n#### Selecting a single Column\n\n```sql\nSELECT first_name\nFROM employees;\n```\n```\n first_name \n------------\n Stella    \n Nathanael\n Lucy\n Mwangi\n Daniel    \n ... --Means there's more in the Data Output\n```\n\n#### Selecting Multiple Columns\nWe separate each column with a comma (,). Allowing us to select more than one column for each query.\n```sql\nSELECT first_name, last_name, department \nFROM employees;\n```\n```\n first_name |  last_name  |   department  \n------------+-------------+---------------\n Stella     | Stephanie  |  Engineering\n Nathanael  | Mutua      |  Marketing\n Lucy       | Wanjiru    |  Director\n ...\n```\n\n### Fetch all columns\nWe use the (*) asterisk symbol. This gives us all the columns from the table.\n```sql\nSELECT * FROM employees;\n```\n\u003e **Avoid SELECT * in production:** Retrieves all columns which can:\n\u003e - Reduce database performance\n\u003e - Increase network traffic\n\u003e - Cause application slowdowns\n\n### Using expressions\n```sql\nSELECT \n  first_name || ' ' || last_name,\n  salary\nFROM employees;\n```\n```\n     ?column?     | salary \n------------------+----------\n Sarah Stephanie  |  89000.00\n Lucy Wanjiru     |  92000.00\n Nathanael Mutua  |  90000.00\n ...\n```\n\u003e Notice the default column name. We'll learn to customize these with aliases in the next section.\n\n### Using WHERE to target and filter\n\n\u003e This will be covered in detail later on\n\nTo filter results based on specific conditions, we can use the WHERE clause. For example, to retrieve employees in the Engineering department:\n\n```sql\nSELECT \n  first_name , last_name, salary\nFROM employees\nWHERE department = 'Engineering';\n```\n```\n     first_name   |      last_name   | salary     |\n------------------+------------------+------------+\n Stella           |  Stephanie       |  85000.00  |\n Daniel           |  Njoroge         |  85000.00  |\n ...\n```\n\n\u003ch2 style=\"padding-top: 100px\" id=\"column-aliases\"\u003e2. Column Aliases\u003c/h2\u003e\n\n### What I will Cover:\n- [Syntax Options](#syntax-options)\n- [Basic Aliasing](#basic-aliasing)\n- [Expression Aliasing](#expression-aliasing)\n- [Aliasing with Special Characters](#aliases-with-special-characters)\n\nThese are temporary names assigned to columns or expressions for readability.\n\n### Syntax Options\n```sql\nSELECT column_name AS alias_name\nSELECT column_name alias_name  -- AS is optional\nSELECT expression AS \"Alias With Space\"\n```\n\n### Examples of Aliasing\n#### Basic aliasing\nWe will replace the column heads for two columns in our employees table.\n\n```sql\nSELECT \n  first_name AS \"First Name\", \n  last_name AS surname\nFROM employees;\n```\n```\n  First Name  |   surname   \n--------------+--------------\n Stella       |   Stephanie\n Nathanael    |   Mutua\n Lucy         |   Wanjiru\n Mwangi       |   Johnson\n ...   \n```\n\n\u003e To alias names with spaces we enclose them in double quotes\n\n#### Expression aliasing\n```sql\nSELECT \n  first_name || ' ' || last_name AS full_name,\n  salary * 1.1 AS proposed_salary\nFROM employees;\n```\n```\n   full_name       | proposed_salary \n-------------------+-----------------\n Stella Stephanie  |        97900.00\n Nathanael Mutua   |        99000.00\n ...\n```\n\n#### Aliases with special characters\nAs seen before we enclose word with spaces in double brackets in order to use them as aliases.\n\n```sql\nSELECT \n  email AS \"Work Email\",\n  salary AS \"Monthly Salary ($)\"\nFROM employees;\n```\n\n```\n     Work Email            |   Monthly Salary\n---------------------------+------------------- \n  s.stephanie@company.com\t |    89000.00\n  nathanael.m@company.com\t |    90000.00\n  l.wanjiru@company.com\t   |    92000.00\n  ...\n```\n\n\u003ch2 style=\"padding-top: 100px\" id=\"order-by-clause\"\u003e3. ORDED BY Clause\u003c/h2\u003e\n\n### What I will cover\n- [Basic Syntax](#basic-syntax-1)\n- [Single Column Sorting](#single-column-sorting)\n- [Multi-column Sorting](#multi-column-sorting)\n- [Sorting By Expression](#sorting-by-expression)\n- [NULL Handling](#null-handling)\n\n\nSorts query results based on specified columns or expressions.\nUsually basically ascending and descending, but we can do more.\n\n### Basic Syntax\n```sql\nSELECT columns\nFROM table\nORDER BY column1 [ASC|DESC], \n         column2 [ASC|DESC];\n```\n\n### Sorting Techniques\n#### Single column sorting\n```sql\nSELECT first_name, hire_date\nFROM employees\nORDER BY hire_date DESC;  -- Newest first\n```\n```\n first_name  |  hire_date\n-------------+-------------\n  Johnson    |  2025-03-01\n  Wilson     |  2024-02-12\n  Mercy      |  2024-02-12\n  Lucy       |  2023-11-05\n  ...\n```\n\n#### Multi-column sorting\n```sql\nSELECT department, first_name, salary\nFROM employees\nORDER BY department ASC, salary DESC;\n```\n```\n   department  |  first_name  |  salary\n---------------+--------------+-----------   \n Director\t     |   Lucy\t      |  92000.00\n Engineering\t |   Stella  \t  |  89000.00\n ...\n```\n#### Sorting by expression\n```sql\nSELECT last_name, first_name\nFROM employees\nORDER BY LENGTH(first_name), last_name;\n```\n```\n   last_name   | \tfirst_name\t|  \n---------------+--------------|\n  Anna    \t   |  Kiptoo\t    |\n  Lucy         |\tWanjiru  \t  |\n ...\n```\n\n#### NULL handling\nIn some tables we may come across null values, it helps that we can identify null values and sort our query according to their position.\n\nFirst, we can ensure they appear last, in a situation wher we do not need to see the Null values.\n```sql\nSELECT first_name, department\nFROM employees\nORDER BY department NULLS LAST;\n```\n\n```\n   first_name  |  department\n---------------+--------------\n    Anna       |     [null]\t \n  ...\n```\n\nSecondly, we can have them appearing at the top of the queried data. This will ensure we can identify them.\n```sql\nSELECT first_name, department\nFROM employees\nORDER BY department NULLS FIRST;\n```\n\n```\n   first_name  |  department\n---------------+--------------\n  ...\n   Anna       |     [null]\t \n```\n\n\u003ch2 style=\"padding-top: 100px\" id=\"select-distinct\"\u003e4. SELECT DISTINCT Clause\u003c/h2\u003e\n\n### What I will cover\n- [Basic Syntax](#basic-syntax-2)\n- [Single Column Distinct](#single-column-distinct)\n- [Multi-column Distinct](#multi-column-distinct)\n- [DISTINCT with Expressions](#distinct-with-expressions)\n\nThis is a clause that removes duplicate rows from query results.\n\n### Basic Syntax\n```sql\nSELECT DISTINCT column1\nFROM table_name;\n\nSELECT DISTINCT column1, column2\nFROM table_name;\n```\n\n### Duplicate Elimination\n#### Single column distinct\nWe can start off by targeting a single column to remove duplicates.\n```sql\nSELECT DISTINCT department \nFROM employees;\n```\n```\n department  \n--------------\n Engineering\n Marketing\n Director\n HR\n null\n```\n\n#### Multi-column distinct\nHere we will select non-duplicates for more than one column.\n\nIn the example below:\nWe are checking for the unique values in ```department``` column, and ```salary``` column.\n\nYou will notice that we have some repeated departments, Don't Worry.\nSo, we first check for unique values in department, which are: ```Engineering```, ```Marketing```, ```Director```,```HR``` and ```null```.\nWhich will appear as we saw in the first query. But with the added ```salary``` column we also check for unique values in the column.\n\nLet's take one department, say ```Engineering```, it has several members, but the unique salaries that do not duplicate are the only ones shown; this is the same to ```Marketing```.\n```sql\nSELECT DISTINCT department, salary\nFROM employees;\n```\n```\n first_name  |  department  \n-------------+--------------\n Marketing   |  42000.00\n [null]      |  75000.00\n HR          |  68000.00\n [null]      |  65000.00\n Engineering |  89000.00\n Engineering |  85000.00\n Director    |  92000.00\n ...\n```\n\n#### DISTINCT with expressions\n```sql\nSELECT DISTINCT \n  salary / 1000 AS salary_band\nFROM employees;\n```\n```\n salary_band \n-------------\n    92.00\n    65.00\n    68.00\n    85.00\n    75.00\n    89.00\n    ...\n```\n\u003e **Performance thought:** DISTINCT sorts results internally which can be costly on large datasets.\n\n\u003ch2 style=\"padding-top: 100px\" id=\"querying-tips\"\u003eQuerying Tips\u003c/h2\u003e\n\n\u003e - **SELECT Specific Columns**: Avoid SELECT * in production, it's kinda risky.\n\u003e - **Use Aliases Wisely**: Improve readability but avoid names that are too long.\n\u003e - **DISTINCT Alternatives**: Consider GROUP BY for complex deduplication.\n\n\u003ch2 style=\"padding-top: 100px\" id=\"postgresql-querying-summary\"\u003ePostgreSQL Querying Summary\u003c/h2\u003e\n\n| Clause/Statement             | Purpose                          | Example                          |\n|--------------------|----------------------------------|----------------------------------|\n| SELECT             | Specify columns to retrieve      | SELECT id, name FROM users       |\n| AS                 | Assign column alias              | SELECT salary * 12 AS annual     |\n| ORDER BY           | Sort results                     | ORDER BY hire_date DESC          |\n| DISTINCT           | Remove duplicates                | SELECT DISTINCT department       |\n| NULLS FIRST/LAST   | Control NULL position in sorts   | ORDER BY score NULLS LAST        |\n\n\u003cp style=\"padding-top: 100px; font-weight: 700; text-align: center;\"\u003ePostgreSQL Querying Tutorial - \u003ci\u003eNash, Stella \u0026 Lucy\u003c/i\u003e\u003c/p\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnathanaelmutua%2Fpostgresql-notes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnathanaelmutua%2Fpostgresql-notes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnathanaelmutua%2Fpostgresql-notes/lists"}