SELECT, WHERE, ORDER BY: Writing Your First Real SQL Server Queries

SELECT, WHERE, ORDER BY: Writing Your First Real SQL Server Queries

This is the query you’ll write more than any other, in some form, for the rest of your career. Getting a genuinely solid mental model here — not just “it works” but why it works in the order it does — pays off in every later chapter.

Anatomy of a SELECT(you type it one way, SQL runs it another)FROMgrab the tableWHEREkeep matching rowsSELECTpick the columnsORDER BYsort what’s leftpredictablebut you TYPED select first — SQL actually runs FROM firstSELECT * is fine forexploring — never inreal app code. It breakssilently when columns change.TOP N without ORDER BY = arbitrary rows —never “the first N you inserted.”

Setup — run this once to follow along:

CREATE TABLE dbo.Restaurant (
    restaurant_id INT IDENTITY(1,1) PRIMARY KEY,
    name          NVARCHAR(100) NOT NULL,
    cuisine       NVARCHAR(50)  NOT NULL,
    city          NVARCHAR(50)  NOT NULL,
    rating        DECIMAL(2,1)  NOT NULL,
    price_range   TINYINT       NOT NULL
);
INSERT INTO dbo.Restaurant (name, cuisine, city, rating, price_range) VALUES
('Spice Route', 'Indian', 'Austin', 4.5, 2),
('Nonna''s Table', 'Italian', 'Austin', 4.7, 3),
('Sakura Grill', 'Japanese', 'Austin', 4.8, 3),
('Taco Libre', 'Mexican', 'Dallas', 4.3, 1);

SELECT: Choose Your Columns

SELECT name, cuisine, rating FROM dbo.Restaurant;

-- SELECT * grabs every column — fine for exploring, avoid it in real application code
SELECT * FROM dbo.Restaurant;

-- Aliasing a column for a cleaner result header
SELECT name AS restaurant_name, rating AS star_rating FROM dbo.Restaurant;
Why avoid SELECT * in real code: it silently breaks if someone adds or reorders columns later, pulls more data over the network than you need, and (once you reach indexing in the advanced course) can prevent the optimizer from using an efficient covering index. Naming columns explicitly costs nothing and avoids all three problems.

WHERE: Filter the Rows

SELECT name, rating FROM dbo.Restaurant WHERE city = 'Austin';

WHERE is evaluated once per row, against the raw table data — it runs before SELECT decides which columns to keep, which is why you can filter on a column you don’t even include in the output.

ORDER BY, DISTINCT, and TOP

SELECT name, rating FROM dbo.Restaurant ORDER BY rating DESC;
SELECT DISTINCT cuisine FROM dbo.Restaurant;
SELECT TOP 3 name, rating FROM dbo.Restaurant ORDER BY rating DESC;
SELECT TOP 25 PERCENT name FROM dbo.Restaurant ORDER BY rating DESC;

TOP without an ORDER BY gives you an arbitrary N rows in whatever order the engine happens to read them — not “the first N you inserted,” and not stable across runs. Always pair TOP with ORDER BY when you mean “the highest/lowest N,” which is almost always what you actually want.

The Order SQL Server Actually Processes Your Query

FROM WHERE SELECT ORDER BY

Even though you type SELECT first, SQL Server processes FROM → WHERE → SELECT → ORDER BY (this is called logical query processing order, and it’s the single most useful mental model for debugging “why doesn’t this work” moments for the rest of this course). That’s why a column alias defined in SELECT can’t be reused in that same query’s WHERE clause — WHERE runs before SELECT even exists:

-- This fails:
SELECT rating * 2 AS double_rating FROM dbo.Restaurant WHERE double_rating > 8;
-- Msg 207: Invalid column name 'double_rating'

-- Because WHERE runs before the alias exists, repeat the expression instead:
SELECT rating * 2 AS double_rating FROM dbo.Restaurant WHERE rating * 2 > 8;

ORDER BY, on the other hand, runs last — after SELECT — which is exactly why it’s the one clause that can reference a column alias.

Comments and Readability

-- single-line comment
/* multi-line
   comment block */
SELECT name, rating -- inline comment on the same line
FROM dbo.Restaurant
WHERE city = 'Austin'; -- Austin locations only

Key Takeaways

  • SELECT picks columns; WHERE filters rows; ORDER BY sorts the result
  • DISTINCT removes duplicate rows; TOP limits row count — always pair TOP with ORDER BY, or “top” is meaningless
  • Logical execution order (FROM → WHERE → SELECT → ORDER BY) explains several “why doesn’t this work” surprises, including why WHERE can’t see a SELECT alias but ORDER BY can
  • Avoid SELECT * outside of quick exploration — name your columns explicitly
Practice tip: Add one more restaurant row of your own, then write three queries against this table from memory before moving to the next lesson: one filtered by cuisine, one sorted by price_range ascending, one using TOP to get the single highest-rated restaurant.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it’s published, and share it with a developer who’d find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server Fundamentals, coming soon on this site.