DBA Diaries

Thoughts and experiences of a DBA working with SQL Server and MySQL

T-SQL – Derived Tables Demonstrated and Explained

Posted on October 18, 2014 Written by Andy Hayes Leave a Comment

T-SQL is a very powerful language when dealing with sets and in this post, I am going to be demonstrating how to use derived tables.

Derived tables are not the same as a temporary or physical tables where the fields and data types are declared. Nor are they subqueries. Instead, as the name implies, the table is derived from an existing table. I liken them to views but a view is an object that is created and is re-usable. A derived table is only available at execution time and not a re-usable object within the query. In other words, you cannot reference it multiple times like you can with common table expressions (CTE’s).

Basic syntax of the derived table

SELECT Field1, Field2
FROM
(SELECT *
FROM Table) Table1

So lets put the syntax to something more real:

USE AdventureWorks2012
GO
SELECT TOP 10 FirstName, LastName
FROM
(SELECT * FROM Person.Person) AS PersonDerivedTable
WHERE LastName = 'Smith';
FirstName       LastName
--------------- ---------------
Abigail         Smith
Adriana         Smith
Alexander       Smith
Alexandra       Smith
Alexis          Smith
Allen           Smith
Alyssa          Smith
Andre           Smith
Andrew          Smith
Arthur          Smith

(10 row(s) affected)

You might be thinking that you can achieve the same thing without the derived table and you would be correct. However where derived tables start to become really useful are when you want to start using aggregated statements.

Derived tables used with aggregated queries

For example, the following query aggregates total sales orders by year as one query and combines the results of the total sales orders per sales rep, per year of the second query. The purpose is to get the percentage of sales orders by sales rep for each year.

USE AdventureWorks2012
GO

SELECT YearTotalsBySalesPerson.*
, YearTotals.TotalOrdersForYear
, CONVERT(DECIMAL(10,2), 100 * CONVERT(DECIMAL(10,2), YearTotalsBySalesPerson.SalesPersonTotalOrders)
/ CONVERT(DECIMAL(10,2), YearTotals.TotalOrdersForYear)) AS PercentageOfSalesForYear
FROM
--total sales orders per year
(SELECT YEAR(OrderDate) AS [Year]
, COUNT(SalesOrderID) AS TotalOrdersForYear
FROM Sales.SalesOrderHeader SOH
WHERE SalesPersonID IS NOT NULL
GROUP BY YEAR(OrderDate)) YearTotals

JOIN
--total sales orders by sales rep per year
(SELECT YEAR(OrderDate) AS [Year]
, SalesPersonID
, COUNT(SalesOrderID) AS SalesPersonTotalOrders
FROM Sales.SalesOrderHeader
WHERE SalesPersonID IS NOT NULL
GROUP BY YEAR(OrderDate), SalesPersonID) YearTotalsBySalesPerson

ON YearTotals.[Year] = YearTotalsBySalesPerson.[Year]

Returning the results (sample)

Year        SalesPersonID SalesPersonTotalOrders TotalOrdersForYear PercentageOfSalesForYear
----------- ------------- ---------------------- ------------------ ---------------------------------------
2008        283           41                     901                4.55
2008        277           97                     901                10.77
2006        289           84                     1015               8.28
2007        279           158                    1524               10.37
2006        278           69                     1015               6.80
2007        285           9                      1524               0.59
2006        275           139                    1015               13.69
2008        286           56                     901                6.22
2005        274           4                      366                1.09
2008        280           12                     901                1.33
2005        282           51                     366                13.93

Derived tables can simplify code writing

Take the following example query which uses a CASE statement combined with GROUP BY

SELECT YEAR(OrderDate) AS [Year]
,CASE WHEN MONTH(OrderDate) IN (1,2,3) THEN 1
WHEN MONTH(OrderDate) IN (4,5,6) THEN 2
WHEN MONTH(OrderDate) IN (7,8,9) THEN 3
WHEN MONTH(OrderDate) IN (10,11,12) THEN 4 END AS [Quarter]
,COUNT(SalesOrderID) AS Orders
FROM Sales.SalesOrderHeader
GROUP BY
YEAR(OrderDate)
,CASE WHEN MONTH(OrderDate) IN (1,2,3) THEN 1
WHEN MONTH(OrderDate) IN (4,5,6) THEN 2
WHEN MONTH(OrderDate) IN (7,8,9) THEN 3
WHEN MONTH(OrderDate) IN (10,11,12) THEN 4 END
ORDER BY [Year], [Quarter]

This can simplified with a derived table.

SELECT [Year], [Quarter], COUNT(SalesOrderID) AS Orders
FROM
(SELECT YEAR(OrderDate) AS [Year]
,CASE WHEN MONTH(OrderDate) IN (1,2,3) THEN 1
WHEN MONTH(OrderDate) IN (4,5,6) THEN 2
WHEN MONTH(OrderDate) IN (7,8,9) THEN 3
WHEN MONTH(OrderDate) IN (10,11,12) THEN 4 END AS [Quarter]
,SalesOrderID
FROM Sales.SalesOrderHeader) YearQuarter
GROUP BY [Year], [Quarter]
ORDER BY [Year], [Quarter]

You can see that there is no need to write the CASE statement twice for the second version.

Summary

  • A derived table cannot be re-used within a query. Consider using a CTE or view in that instance.
  • A derived table is not a physical object within the database, it only exists at execution time.
  • Derived tables are not exclusive to SQL Server, other RDBMS systems support them, MySQL, Oracle, etc.
  • They are great for performing extra calculations on aggregated queries by enabling you to join sets of data together.
  • Can be used to help simply code writing, for example GROUP BY CASE WHEN statements as above.

Filed Under: All Articles, SQL Tips and Tricks Tagged With: sql, sql server, t-sql

Using SELECT TOP WITH TIES in SQL Server

Posted on June 11, 2014 Written by Andy Hayes 2 Comments

I’ve used SELECT TOP (x) many, many times. After learning how to use SELECT, it’s something I quickly learned to use and remains something which I continue to use often.

I’ve also used TOP (x) with UPDATE and DELETE statements to limit the number of rows updated or deleted in a statement. I’ve never had to use SELECT TOP WITH TIES though.

I’ve glanced through the documentation in the past and thought – “must learn that one day” but never had the time or need to. I guess some things you learn how to use only when you have to.

So this post is dedicated to my learning experience of using SELECT TOP WITH TIES 🙂

What does SELECT TOP WITH TIES do?

Let’s take an example. Say you wanted to retrieve the first 5 rows from a table and you ordered by a specific column. So you get back 10 rows ordered by your column.

Now apply SELECT TOP (5) WITH TIES and any row which has a column value that matches the last row’s column value as defined by the ORDER BY clause will also be returned in the results. So you get more rows than what is specified in TOP (x).

Let’s do an example 🙂

CREATE TABLE FamousTransformers
(ID SMALLINT PRIMARY KEY IDENTITY(1,1),
FirstName VARCHAR(100) NOT NULL,
LastName VARCHAR(100) NOT NULL,
FavouriteColour VARCHAR(50) NOT NULL);

--populate with some data (6 rows to demonstrate this working)
INSERT INTO FamousTransformers(FirstName, LastName, FavouriteColour)
VALUES('Clark','Kent','Blue');
INSERT INTO FamousTransformers(FirstName, LastName, FavouriteColour)
VALUES('Bruce','Wayne','Black');
INSERT INTO FamousTransformers(FirstName, LastName, FavouriteColour)
VALUES('Peter','Parker','Red');
INSERT INTO FamousTransformers(FirstName, LastName, FavouriteColour)
VALUES('Optimus','Prime','Red');
INSERT INTO FamousTransformers(FirstName, LastName, FavouriteColour)
VALUES('David','Banner','Green');
INSERT INTO FamousTransformers(FirstName, LastName, FavouriteColour)
VALUES('Rodimus','Prime','Orange');

--select using normal TOP(x)

SELECT TOP (5) FirstName, LastName, FavouriteColour
FROM FamousTransformers
ORDER BY FavouriteColour

Returns….

FirstName            LastName             FavouriteColour
-------------------- -------------------- --------------------
Bruce                Wayne                Black
Clark                Kent                 Blue
David                Banner               Green
Rodimus              Prime                Orange
Optimus              Prime                Red

(5 row(s) affected)
--now execute using WITH TIES
SELECT TOP (5) WITH TIES FirstName, LastName, FavouriteColour
FROM FamousTransformers
ORDER BY FavouriteColour

FirstName            LastName             FavouriteColour
-------------------- -------------------- --------------------
Bruce                Wayne                Black
Clark                Kent                 Blue
David                Banner               Green
Rodimus              Prime                Orange
Peter                Parker               Red
Optimus              Prime                Red

(6 row(s) affected)

So you can see the extra row appearing there where “Optimus Prime” is displayed because he has the same favourite colour as “Peter Parker”. The FavouriteColour column is the key here as defined in the ORDER BY statement.

Actual use cases for SELECT TOP WITH TIES

I can think of one straight off the top of my head. If you had a league table of top performing sales people and wanted to bring back the top three performers, what if two sales people were tied for 3rd and 4th place on revenue? No way to differentiate them, they should both be returned in the results and share 3rd place.

And finally….

You must use ORDER BY and TOP clauses together if you want to use WITH TIES.

Filed Under: All Articles, SQL Tips and Tricks Tagged With: sql server, t-sql

How to Rename a SQL Server Column or Table Using T-SQL

Posted on November 20, 2013 Written by Andy Hayes Leave a Comment

I would typically use Management Studio to rename columns or tables in SQL Server. Afterall, it is an easy thing to do to open up the GUI make your changes and then save them back to the SQL Server.

Have you ever been in a situation where you wanted to make a number of such changes and then later on you needed to repeat those changes on another system?

I was in such a situation recently where due to some application changes, many columns had to be renamed, the application tested and then I had to repeat the procedure on production.

I did not want to have to open up every table in Management Studio and click the save button each time all over again!

I needed something that I could execute quickly, so I prepared a file of T-SQL commands to make my changes in one swift stroke. I achieved it all using sp_rename

T-SQL example – renaming columns and tables

So here we have an example for renaming a column:

EXEC sp_rename 'Table.[OldColumnName]', '[NewColumnName]', '[COLUMN]';

If we wanted to rename a table then we can use:

EXEC sp_rename '[OldTableName]', '[NewTableName]';

Note that the square brackets are not mandatory but are necessary when you have silly database designers who have put such things as hyphens or spaces in their field names. Makes me cringe just thinking about it! 😐

Permissions needed for sp_rename

You need ALTER permission if you want to rename tables or columns.

One final note

You can use sp_rename for renaming other objects besides tables. It can also be used for renaming indexes, constraints, types databases and statistics. More more information on this useful little proc, visit this link

Filed Under: All Articles, SQL Tips and Tricks Tagged With: sql server, t-sql

Differences Between TRUNCATE TABLE and DELETE

Posted on May 19, 2013 Written by Andy Hayes 3 Comments

If you want to remove data from a table, you can do this in a couple of ways using TRUNCATE TABLE or DELETE. A common approach is to use DELETE to remove all rows in the table but TRUNCATE TABLE offers an alternative and I will list what the differences between the two are.

DELETE

--Delete rows with filter
DELETE FROM SchemaName.Table WHERE...

--Delete all rows
DELETE SchemaName.Table

--Delete all rows
DELETE FROM SchemaName.Table

--Delete using JOINS
DELETE T1
FROM SchemaName.Table1 AS T1
JOIN SchemaName.Table2 AS T2 ON T1.Column1 = T2.Column1

--Delete using IN
DELETE FROM SchemaName.Table1
WHERE Column1 IN (SELECT Column1 FROM SchemaName.Table2)

--Delete using EXISTS
DELETE T1
FROM SchemaName.Table1 AS T1
WHERE EXISTS
(SELECT *
FROM SchemaName.Table2 AS T2
WHERE T1.Column1 = T2.Column1)

  • Provides more control over what data is and can be deleted.
  • Will not reseed the identity value on an identity column
  • Can be used where the DELETE operation does not violate foreign key constraint
  • Can be a slow operation if the table is large
  • Locking can be an issue if the operation is removing many rows
  • Will fire triggers
  • Transactions can be rolled back as LSN (log sequence number) is maintained in the transaction log
  • Data pages consumed may need to be reclaimed using a DBCC SHRINKDATABASE operation
  • DELETE will typically consume more transaction log space because of extra logging

TRUNCATE TABLE

TRUNCATE TABLE Schema.TableName;

  • WHERE clause is not optional – it will remove all data from your table
  • Reseeds the identify value of an identity column
  • Cannot be used on a table which is referenced by a foreign key constraint
  • Can be considerably quicker than DELETE due to deallocation of data pages and minimal logging
  • Cannot be used in replication or log shipping
  • Will not fire triggers
  • Cannot be used on tables which are part of an indexed view
  • Who has permission: table owner, sysadmin, db_owner, db_ddladmin or any user with ALTER permission on the table

I wanted to expand on the differences in speed between the two operations.

When TRUNCATE TABLE is issued against a table, all the data pages are deallocated which are used to store the tables data. Compared with a DELETE, this is significantly faster as each DELETE operation is logged in the transaction log but only the deallocations are logged in the transaction log for a TRUNCATE operation.

The DELETE operation will consume database resource and locks and can therefore be considerably slower and have greater impact on your system in comparison to TRUNCATE TABLE. See this post on reducing overhead for large delete operations.

As each DELETE operation is logged inside of the transaction log, it is possible to rollback to a point in time but with TRUNCATE TABLE it is not possible to have this level of precision. In a rollback scenario, only a complete rollback could be performed.

As with a DELETE it is also possible to rollback a TRUNCATE if it has not yet been committed. You can do this by using transactions like in this very simple example:

BEGIN TRAN
TRUNCATE TABLE SchemaName.Table
--test success here
ROLLBACK TRAN
ELSE
COMMIT TRAN

Time to wrap this up..

So there are a number of differences between the two. Both operations have their pros and cons and provide you with a choice over how you want to remove your data.

 

Filed Under: All Articles, SQL Tips and Tricks Tagged With: sql server, t-sql

  • « Previous Page
  • 1
  • 2
  • 3
  • 4
  • 5
  • Next Page »

Categories

  • All Articles (82)
  • Career Development (8)
  • MySQL Administration (18)
  • MySQL Performance (2)
  • SQL Server Administration (24)
  • SQL Server News (3)
  • SQL Server Performance (14)
  • SQL Server Security (3)
  • SQL Tips and Tricks (19)

Top 10 Popular Posts

  • Using sp_change_users_login to fix SQL Server orphaned users
  • How to shrink tempdb
  • MySQL SHOW USERS? – How to List All MySQL Users and Privileges
  • How to Transfer Logins to Another SQL Server or Instance
  • How to Delete Millions of Rows using T-SQL with Reduced Impact
  • T-SQL – How to Select Top N Rows for Each Group Using ROW_NUMBER()
  • New T-SQL features in SQL Server 2012 – OFFSET and FETCH
  • How to Kill All MySQL Processes For a Specific User
  • Using exec sp_who2 to help with SQL Server troubleshooting
  • How to move tempdb

Recent Posts

  • How to Setup MySQL Master Master Replication
  • How To Use SQL to Convert a STRING to an INT
  • How to set up MySQL Replication Tutorial
  • How to Use SQL CASE for Conditional Logic in Your SQL Queries
  • Using ISNULL in SQL Server to Replace NULL Values

Search

Connect

  • Twitter
  • Facebook
  • Google+
  • RSS

About

  • Cookie Policy
  • Disclaimer
  • About
Copyright © ‘2021’ DBA Diaries built on the Genesis Framework

This site uses cookies. We assume you are happy with cookies but click the link if you are not. Close