Skip to content

Bits of .NET

Daily micro-tips for C#, SQL, performance, and scalable backend engineering.

  • Asp.Net Core
  • C#
  • SQL
  • JavaScript
  • CSS
  • About
  • ErcanOPAK.com
  • No Access
  • Privacy Policy

Category: SQL

SQL

SQL: Reading Execution Plans to Eliminate Table Scans

- 21.02.26 - ErcanOPAK comment on SQL: Reading Execution Plans to Eliminate Table Scans

A query might look clean but run slow. Execution Plans show you if SQL is using an Index or doing a ‘Table Scan’. If you see ‘Scan’, you need an index.

Read More
SQL

SQL: Calculate Running Totals with ROW_NUMBER() and OVER()

- 21.02.26 - ErcanOPAK comment on SQL: Calculate Running Totals with ROW_NUMBER() and OVER()

Window functions allow you to perform calculations across sets of rows related to the current row. SELECT Name, Salary, SUM(Salary) OVER(ORDER BY HireDate) as RunningTotal FROM Employees;

Read More
SQL

SQL: Use CTEs (Common Table Expressions) for Readable Queries

- 21.02.26 - ErcanOPAK comment on SQL: Use CTEs (Common Table Expressions) for Readable Queries

Stop using complex subqueries. CTEs make your SQL look like clean code. WITH MonthlySales AS ( SELECT ProductId, SUM(Amount) as Total FROM Sales GROUP BY ProductId ) SELECT * FROM MonthlySales WHERE Total > 1000;

Read More
SQL

SQL: Use Computed Columns for Automatic Calculated Values

- 21.02.26 - ErcanOPAK comment on SQL: Use Computed Columns for Automatic Calculated Values

Calculating values in application code requires logic duplication. Computed columns calculate automatically in database. Create Computed Column: CREATE TABLE Orders ( OrderId INT PRIMARY KEY, Quantity INT, PricePerUnit DECIMAL(10,2), — Computed column (calculated automatically) TotalPrice AS (Quantity * PricePerUnit), — Persisted (stored, can be indexed) TotalWithTax AS (Quantity * PricePerUnit * 1.1) PERSISTED ); Automatic […]

Read More
SQL

SQL: Use Window Functions for Running Totals and Ranking

- 21.02.26 - ErcanOPAK comment on SQL: Use Window Functions for Running Totals and Ranking

Calculating running totals or row rankings with self-joins is complex. Window functions do it elegantly. Running Total: SELECT Date, Amount, SUM(Amount) OVER (ORDER BY Date) AS RunningTotal FROM Sales ORDER BY Date; — Output: — 2024-01-01 100 100 — 2024-01-02 150 250 — 2024-01-03 200 450 Rank Within Groups: SELECT Department, EmployeeName, Salary, RANK() OVER […]

Read More
SQL

SQL: Use STRING_AGG to Concatenate Rows into Comma-Separated List

- 17.02.26 - ErcanOPAK comment on SQL: Use STRING_AGG to Concatenate Rows into Comma-Separated List

Collecting multiple rows into one comma-separated string used to require cursors. STRING_AGG does it in one line. Basic Usage: — Get all tags for each post SELECT PostId, STRING_AGG(TagName, ‘, ‘) AS Tags FROM PostTags GROUP BY PostId; — Result: — PostId Tags — 1 CSS, HTML, JavaScript — 2 SQL, Database, Performance With Ordering: […]

Read More
SQL

SQL: Use Filtered Indexes to Index Only Subset of Rows

- 17.02.26 - ErcanOPAK comment on SQL: Use Filtered Indexes to Index Only Subset of Rows

Regular index on status column with 95% ‘active’ rows is inefficient. Filter index to index only relevant rows. Problem – Full Index: — Index includes ALL rows (95% active, 5% inactive) CREATE INDEX IX_Orders_Status ON Orders(Status); — Query only needs inactive SELECT * FROM Orders WHERE Status = ‘inactive’; — Reads huge index to find […]

Read More
SQL

SQL: Use PIVOT to Transform Rows into Columns

- 16.02.26 - ErcanOPAK comment on SQL: Use PIVOT to Transform Rows into Columns

Displaying row data as columns manually requires complex CASE statements. PIVOT does it automatically. Source Data: Month Product Sales January Widget 100 January Gadget 150 February Widget 120 February Gadget 180 PIVOT Query: SELECT * FROM ( SELECT Month, Product, Sales FROM SalesData ) AS SourceTable PIVOT ( SUM(Sales) FOR Product IN ([Widget], [Gadget]) ) […]

Read More
SQL

SQL: Use MERGE OUTPUT to Track What Changed During Upsert

- 16.02.26 - ErcanOPAK comment on SQL: Use MERGE OUTPUT to Track What Changed During Upsert

After MERGE, don’t know what was inserted vs updated? OUTPUT clause captures the changes. MERGE with OUTPUT: MERGE INTO Products AS target USING @NewProducts AS source ON target.ProductId = source.ProductId WHEN MATCHED THEN UPDATE SET Price = source.Price WHEN NOT MATCHED THEN INSERT (ProductId, Name, Price) VALUES (source.ProductId, source.Name, source.Price) OUTPUT $action AS Action, INSERTED.ProductId, […]

Read More
SQL

SQL: Use EXPLAIN to See Query Execution Plan and Find Bottlenecks

- 15.02.26 - ErcanOPAK comment on SQL: Use EXPLAIN to See Query Execution Plan and Find Bottlenecks

Query slow but don’t know why? EXPLAIN shows exactly how database executes it. Basic Usage: EXPLAIN SELECT * FROM Orders WHERE CustomerId = 123; — Output shows: — – Table scan or index usage — – Number of rows examined — – Join order — – Estimated cost PostgreSQL Analyze: EXPLAIN ANALYZE SELECT * FROM […]

Read More
SQL

SQL: Use CTEs to Make Complex Queries Readable

- 15.02.26 - ErcanOPAK comment on SQL: Use CTEs to Make Complex Queries Readable

Nested subqueries are impossible to read. CTEs (Common Table Expressions) break them into named, readable chunks. Messy Nested Query: SELECT * FROM Orders o WHERE o.CustomerId IN ( SELECT CustomerId FROM Customers WHERE Country IN ( SELECT Country FROM TopCountries WHERE Revenue > 1000000 ) ); Clean CTE Version: WITH TopCountries AS ( SELECT Country […]

Read More
SQL

SQL: Use HAVING to Filter Aggregated Results

- 15.02.26 - ErcanOPAK comment on SQL: Use HAVING to Filter Aggregated Results

WHERE can’t filter aggregated data. HAVING filters after GROUP BY. Wrong – WHERE with Aggregate: SELECT CustomerID, COUNT(*) AS OrderCount FROM Orders WHERE COUNT(*) > 5 — ERROR! Can’t use aggregate in WHERE GROUP BY CustomerID; Correct – HAVING: SELECT CustomerID, COUNT(*) AS OrderCount FROM Orders GROUP BY CustomerID HAVING COUNT(*) > 5; — Filters […]

Read More
SQL

SQL: Use CROSS JOIN to Generate All Possible Combinations

- 15.02.26 - ErcanOPAK comment on SQL: Use CROSS JOIN to Generate All Possible Combinations

Need all combinations of two sets? CROSS JOIN creates cartesian product. Example – All Size/Color Combinations: — Sizes table: S, M, L — Colors table: Red, Blue, Green SELECT s.size, c.color FROM Sizes s CROSS JOIN Colors c; — Result (9 combinations): — S, Red — S, Blue — S, Green — M, Red — […]

Read More
SQL

SQL: Use TRY_CAST Instead of CAST to Avoid Conversion Errors

- 14.02.26 - ErcanOPAK comment on SQL: Use TRY_CAST Instead of CAST to Avoid Conversion Errors

CAST throws error on invalid data. TRY_CAST returns NULL instead – safer for user input. CAST – Throws Error: SELECT CAST(‘123’ AS INT); — Works: 123 SELECT CAST(‘abc’ AS INT); — Error: Conversion failed! — Query crashes, returns nothing TRY_CAST – Returns NULL: SELECT TRY_CAST(‘123’ AS INT); — Returns: 123 SELECT TRY_CAST(‘abc’ AS INT); — […]

Read More
SQL

SQL: Use ISNULL vs COALESCE Correctly for Best Performance

- 14.02.26 - ErcanOPAK comment on SQL: Use ISNULL vs COALESCE Correctly for Best Performance

Both replace NULL values but work differently. ISNULL is faster, COALESCE is more flexible. ISNULL – SQL Server Specific: — Takes exactly 2 arguments, returns first if not null SELECT ISNULL(MiddleName, ”) AS MiddleName FROM Users; — Faster – compiled inline — Data type from first argument COALESCE – ANSI Standard: — Takes 2+ arguments, […]

Read More
SQL

SQL: Use CHAR Instead of VARCHAR for Fixed-Length Columns to Save Space

- 13.02.26 - ErcanOPAK comment on SQL: Use CHAR Instead of VARCHAR for Fixed-Length Columns to Save Space

Storing 2-letter country codes as VARCHAR(50)? Use CHAR for fixed-length data to optimize storage. When to Use CHAR: — Always exactly 2 characters CountryCode CHAR(2) — ‘US’, ‘UK’, ‘FR’ — Always exactly 1 character IsActive CHAR(1) — ‘Y’ or ‘N’ — Fixed format PhoneArea CHAR(3) — ‘555’, ‘212’, ‘415’ When to Use VARCHAR: — Variable […]

Read More
SQL

SQL: Use CROSS APPLY Instead of Subqueries for Better Performance

- 13.02.26 - ErcanOPAK comment on SQL: Use CROSS APPLY Instead of Subqueries for Better Performance

Correlated subqueries run once per row. CROSS APPLY runs more efficiently and is easier to read. Slow Subquery: SELECT c.CustomerName, (SELECT TOP 1 OrderDate FROM Orders o WHERE o.CustomerId = c.Id ORDER BY OrderDate DESC) AS LastOrderDate FROM Customers c; — Runs subquery for EVERY customer Fast CROSS APPLY: SELECT c.CustomerName, o.OrderDate AS LastOrderDate FROM […]

Read More
SQL

SQL: Use EXISTS Instead of COUNT for Checking Existence

- 13.02.26 - ErcanOPAK comment on SQL: Use EXISTS Instead of COUNT for Checking Existence

Checking if records exist with COUNT(*) > 0 is slow. EXISTS stops at first match. Slow Way: IF (SELECT COUNT(*) FROM Orders WHERE CustomerId = 123) > 0 BEGIN PRINT ‘Customer has orders’ END — Counts ALL orders even though we only need to know if ANY exist Fast Way: IF EXISTS (SELECT 1 FROM […]

Read More
SQL

SQL: Use COALESCE to Replace NULL Values Inline

- 13.02.26 - ErcanOPAK comment on SQL: Use COALESCE to Replace NULL Values Inline

Don’t use CASE WHEN for simple NULL checks. COALESCE is cleaner. Verbose Way: SELECT CASE WHEN Name IS NULL THEN ‘Unknown’ ELSE Name END AS Name FROM Users; Clean Way: SELECT COALESCE(Name, ‘Unknown’) AS Name FROM Users; Multiple Fallbacks: SELECT COALESCE(MobilePhone, WorkPhone, HomePhone, ‘No phone’) AS Phone FROM Users; Returns first non-NULL value.

Read More
SQL

SQL Window Functions: Analytics Queries That Replace Hundreds of Lines of Code

- 05.02.26 - ErcanOPAK comment on SQL Window Functions: Analytics Queries That Replace Hundreds of Lines of Code

Writing complex analytical queries with self-joins and subqueries? Window functions perform calculations across rows without grouping. Common Window Function Patterns: — Basic structure SELECT column1, column2, WINDOW_FUNCTION() OVER ( PARTITION BY partition_column ORDER BY sort_column ROWS/RANGE BETWEEN frame_start AND frame_end ) AS calculated_column FROM table_name; — Available functions: — Ranking: ROW_NUMBER(), RANK(), DENSE_RANK(), NTILE() — […]

Read More
SQL

SQL Server Indexing Secret: How Covered Indexes Can Make Queries 100x Faster

- 05.02.26 - ErcanOPAK comment on SQL Server Indexing Secret: How Covered Indexes Can Make Queries 100x Faster

Your SQL queries running slow even with indexes? Discover how covered indexes eliminate key lookups and dramatically improve performance. The Problem: Non-Covered Index — Table structure CREATE TABLE Orders ( Id INT PRIMARY KEY, CustomerId INT, OrderDate DATETIME, TotalAmount DECIMAL(10,2), Status VARCHAR(50), ShippingAddress NVARCHAR(500), — 20 more columns… ); — Common query SELECT CustomerId, OrderDate, […]

Read More
SQL

SQL: Use MERGE to Upsert (Insert or Update) in One Statement

- 03.02.26 - ErcanOPAK comment on SQL: Use MERGE to Upsert (Insert or Update) in One Statement

Inserting if row doesn’t exist, updating if it does? MERGE statement does both in one atomic operation without race conditions. The Problem – Separate Insert/Update: — Check if exists IF EXISTS (SELECT 1 FROM Products WHERE ProductId = @Id) BEGIN — Update UPDATE Products SET ProductName = @Name, Price = @Price WHERE ProductId = @Id; […]

Read More
SQL

SQL: Use Window Functions to Calculate Running Totals Without Self-Joins

- 03.02.26 - ErcanOPAK comment on SQL: Use Window Functions to Calculate Running Totals Without Self-Joins

Need running totals, rankings, or moving averages? Window functions do it in one query without complex self-joins or cursors. The Old Painful Way – Self-Join: — Calculate running total of sales SELECT o1.OrderDate, o1.Amount, (SELECT SUM(o2.Amount) FROM Orders o2 WHERE o2.OrderDate

Read More
SQL

SQL: When CTEs Kill Performance and You Should Use Temp Tables Instead

- 01.02.26 - ErcanOPAK comment on SQL: When CTEs Kill Performance and You Should Use Temp Tables Instead

Common Table Expressions (CTEs) make queries readable but can cause performance disasters when SQL Server evaluates them multiple times. The CTE Performance Trap: — ❌ BAD: CTE evaluated 3 times! WITH RecentOrders AS ( SELECT CustomerId, OrderDate, Total FROM Orders WHERE OrderDate >= DATEADD(month, -1, GETDATE()) — Complex calculation that takes 5 seconds ) SELECT […]

Read More
SQL

SQL Indexing: Why Your Query Ignores Indexes and Scans 10 Million Rows Instead

- 01.02.26 - ErcanOPAK comment on SQL Indexing: Why Your Query Ignores Indexes and Scans 10 Million Rows Instead

Created an index but your query still takes 30 seconds? SQL Server might be ignoring it due to implicit conversions, functions, or wildcard positioning. Index Killer #1 – Functions on Indexed Columns: — Index exists on CreatedDate CREATE INDEX IX_Orders_CreatedDate ON Orders(CreatedDate); — ❌ BAD: Index ignored, full table scan SELECT * FROM Orders WHERE […]

Read More
SQL

Fix Deadlocks by Understanding Lock Ordering and Using Proper Isolation Levels

- 01.02.26 | 01.02.26 - ErcanOPAK comment on Fix Deadlocks by Understanding Lock Ordering and Using Proper Isolation Levels

Getting “Transaction was deadlocked” errors randomly? Deadlocks happen when two transactions lock resources in opposite order. Here’s how to fix them permanently. Identify Deadlocks – System Health Session: — SQL Server automatically logs deadlocks to system_health session SELECT CAST(target_data AS XML) AS deadlock_xml FROM sys.dm_xe_session_targets st JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address WHERE s.name […]

Read More
SQL

SQL Server: Find Slow Queries with Query Store (No Third-Party Tools Needed)

- 01.02.26 | 01.02.26 - ErcanOPAK comment on SQL Server: Find Slow Queries with Query Store (No Third-Party Tools Needed)

Application running slow but can’t figure out which queries are the culprits? Query Store is SQL Server’s built-in performance tracker that records everything. Enable Query Store (SQL Server 2016+): — Enable for your database ALTER DATABASE YourDatabaseName SET QUERY_STORE = ON ( OPERATION_MODE = READ_WRITE, DATA_FLUSH_INTERVAL_SECONDS = 900, INTERVAL_LENGTH_MINUTES = 60, MAX_STORAGE_SIZE_MB = 1000, QUERY_CAPTURE_MODE […]

Read More
SQL

Why COUNT(*) Gets Slow on “Big Enough” Tables

- 31.01.26 - ErcanOPAK comment on Why COUNT(*) Gets Slow on “Big Enough” Tables

It’s not the count.It’s locking + metadata access. Reality COUNT must respect: Isolation level Pending writes Allocation metadata Production alternative Use approximate counts for dashboards. Why Accuracy isn’t always worth blocking.

Read More
SQL

Why Your Index Exists But Is Never Used

- 31.01.26 - ErcanOPAK comment on Why Your Index Exists But Is Never Used

The index is fine.The predicate is not. Example WHERE YEAR(OrderDate) = 2024 Why it fails Functions on columns prevent index seeks. Rewrite WHERE OrderDate >= ‘2024-01-01’ AND OrderDate < ‘2025-01-01’ Cause → Effect Function → scan → CPU spike → slow queries.

Read More
SQL

Why Indexes Sometimes Make Queries Slower

- 30.01.26 - ErcanOPAK comment on Why Indexes Sometimes Make Queries Slower

Indexes are not magic. Bad case Low-selectivity columns Over-indexing Diagnosis SET STATISTICS IO ON; Why Wrong index = more lookups than scans.

Read More
Page 2 of 9
« Previous 1 2 3 4 5 6 7 … 9 Next »

Posts navigation

Older posts
Newer posts
April 2026
M T W T F S S
 12345
6789101112
13141516171819
20212223242526
27282930  
« Mar    

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (950)
  • How to add default value for Entity Framework migrations for DateTime and Bool (859)
  • Get the First and Last Word from a String or Sentence in SQL (837)
  • How to select distinct rows in a datatable in C# (805)
  • How to make theater mode the default for Youtube (754)
  • Add Constraint to SQL Table to ensure email contains @ (578)
  • How to enable, disable and check if Service Broker is enabled on a database in SQL Server (564)
  • Average of all values in a column that are not zero in SQL (531)
  • How to use Map Mode for Vertical Scroll Mode in Visual Studio (489)
  • Find numbers with more than two decimal places in SQL (449)

Recent Posts

  • C#: Use Init-Only Setters for Immutable Objects After Construction
  • C#: Use Expression-Bodied Members for Concise Single-Line Methods
  • C#: Enable Nullable Reference Types to Eliminate Null Reference Exceptions
  • C#: Use Record Types for Immutable Data Objects
  • SQL: Use CTEs for Readable Complex Queries
  • SQL: Use Window Functions for Advanced Analytical Queries
  • .NET Core: Use Background Services for Long-Running Tasks
  • .NET Core: Use Minimal APIs for Lightweight HTTP Services
  • Git: Use Cherry-Pick to Apply Specific Commits Across Branches
  • Git: Use Interactive Rebase to Clean Up Commit History Before Merge

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (950)
  • How to add default value for Entity Framework migrations for DateTime and Bool (859)
  • Get the First and Last Word from a String or Sentence in SQL (837)
  • How to select distinct rows in a datatable in C# (805)
  • How to make theater mode the default for Youtube (754)

Recent Posts

  • C#: Use Init-Only Setters for Immutable Objects After Construction
  • C#: Use Expression-Bodied Members for Concise Single-Line Methods
  • C#: Enable Nullable Reference Types to Eliminate Null Reference Exceptions
  • C#: Use Record Types for Immutable Data Objects
  • SQL: Use CTEs for Readable Complex Queries

Social

  • ErcanOPAK.com
  • GoodReads
  • LetterBoxD
  • Linkedin
  • The Blog
  • Twitter
© 2026 Bits of .NET | Built with Xblog Plus free WordPress theme by wpthemespace.com