Thursday, November 15, 2012

Computed Column in SQL Server


How do you create Computed/Calculated column in SQL Server?
A computed column is computed based on an expression that can use other columns of the same table. The expression can be a non-computed column name, constant, function, and any combination of these connected by one or more operators. However, the expression cannot be a sub-query.
 

Scenario: I want to create a computed column which should be calculated based on the values of other columns. For instance, Employee table has DateOfBirth column and I want to create a computed column to store the Age of an employee (in years). Another example could be to display the Grade of a student based on the marks obtained by the student.

Example 1: Employee (EmployeeID, EmployeeName, BasicSalary, DOB)
EmployeeID
EmployeeName
BasicSalary
DOB
1
Hari
5000
1983-05-05
2
John
3500
1978-10-25
3
Peter
4500
1982-02-10
4
Ravi
2500
1980-03-04
5
Max
3600
1985-09-20

Problem: Add a new computed column Age in Employee table.

Example 2: Student (StudentID, StudentName, MarksObtained)
EmployeeID
EmployeeName
MarksObtained
1
Hari
74
2
John
80
3
Peter
55
4
Ravi
34
5
Max
67

Problem: Add a new computed column Grade in Student table using following grading system:
If MarksObtained >= 75 then A
If MarksObtained >= 60 then B
If MarksObtained >= 40 then C
Else F
 

Friday, November 2, 2012

CONCATENATE Column values into Rows


How do you CONCATENATE column values into rows?

Scenario: There is a table Student (ID (identity), StudentName, SubjectName). You need to concatenate all the subject of each student and display along with student name. Below is sample of input data:

ID
StudentName
SubjectName
1
Hari
Science
2
Tony
Biology
3
Hari
Maths
4
Ravi
Physics
5
Ravi
Chemistry
6
Ravi
Botany

 
Here is the expected output:

StudentName
SubjectName
Hari
Science,Maths
Ravi
Physics,Chemistry,Botany
Tony
Biology

 
Here is the solution: 

Thursday, October 4, 2012

SQL Fun #01

Write shortest T-SQL code to print 0.00 without using any number and built-in function

Monday, October 1, 2012

What is Tally Table in SQL Server?

In this post, I am going to explain about Tally table and it’s uses in T-SQL programming.

A Tally table is like any other table but having a single column of sequential numbers, values starting from 1 (or 0) to some N (int) number.
The largest number in the Tally table should be based on what suits your system, application, or database most. So don't use very high number. Also column of Tally should be indexed for better performance.

I use Tally table to generate 25 years of dates, so my Tally tables will have values from 1 to 10,000 (25 years * 365.25 days = 9131.25)


How to Create a Tally Table
There are several methods to create a Tally table. I will use one of the simplest and obvious option - WHILE loop because it's easier to explain and simpler than others.



SET NOCOUNT ON;
IF OBJECT_ID('dbo.Tally') IS NOT NULL   DROP TABLE dbo.Tally
GO

-- Define how many rows you want in Tally table.
-- I am inserting only 10000 rows
SET ROWCOUNT 10000

SELECT IDENTITY(INT, 1, 1) ID
INTO dbo.Tally
FROM master.sys.all_columns c
CROSS JOIN master.sys.all_columns c1
-- you may use one more cross join if tally table required hundreds of million rows

SET ROWCOUNT 0

-- ADD (unique) clustered index
CREATE UNIQUE CLUSTERED INDEX PKC_Tally ON dbo.Tally (ID)
GO

 
How to use Tally table in T-SQL and what are the advantages?

There are several advantages of a Tally table. Here are some of the examples:

Ø  To generate Date Range for given Start Date and End Date

Ø  To Manipulate strings, like:

·         Find the positions of a character in a string.

·         Find the total occurances of a character in a string
·         Split comma seperated values
 
I will explain these advantages with examples.

Generate Date Range using Tally Table

Generally you would require a WHILE loop to create Date Range values. However, it is very easy to generate date range using tally. Its much faster than WHILE loop:
 
-- Generate Date range
DECLARE @BeginDate DATE = '2001-01-01', @EndDate DATE = '2025-12-31'
SELECT DATEADD(DD, ID-1, @BeginDate) [Date]
,DAY(DATEADD(DD, ID-1, @BeginDate)) [Day]
,MONTH(DATEADD(DD, ID-1, @BeginDate)) [Month]
,YEAR(DATEADD(DD, ID-1, @BeginDate)) [Year]
FROM dbo.Tally
WHERE ID <= DATEDIFF(DD, @BeginDate, @EndDate) + 1
Here is the output:

 


 

 













Find a Character Positions in a String using Tally Table

You can find a character position using string functions and WHILE loop. But Tally table makes it much simpler than any other method, yet faster. Here is an example:

-- Find the position numbers of comma in a given string.
DECLARE @Str VARCHAR(1000), @FindChar CHAR(1) = ','
SET @Str = 'Hari,Jon,Ravi,Vijay,Peter,Max' --Input String
 
SELECT ID AS CharPosition
FROM dbo.Tally 
WHERE ID <= LEN(@Str) 
AND SUBSTRING(@Str, ID, 1) = @FindChar
ORDER BY ID

 

Here is the output:

 



 

 









Find count of all the occurrences of a Character in a String using Tally Table

You can find the count of all the occurrences of a character in a string using Tally table by slightly modifying above query:
 
-- Find the occurrences of a character in a given string.
DECLARE @Str VARCHAR(1000), @FindChar CHAR(1) = 'a'
SET @Str = 'Hari,Jon,Ravi,Vijay,Peter,Max' --Input String

SELECT COUNT(1) AS CharCount
FROM (
SELECT ID AS CharPosition
FROM dbo.Tally 
WHERE ID <= LEN(@Str) 
AND SUBSTRING(@Str, ID, 1) = @FindChar
) AS Temp
 

Here is the output:

 

 













Split Comma Seperated values using Tally table

I had posted a separate article about Function to Split Multi-valued String couple of years back.

The logic implemented in that function could be much simpler by using Tally table. You can split the values without WHILE loop. It would be interesting to compare the performance of these two mechanism.

--Split Comma Seperated values
DECLARE @Str VARCHAR(1000), @Delimiter CHAR(1) = ','
SET @Str = 'Hari,Jon,Ravi,Vijay,Peter,Max'

-- Append delimiter at the beginning and end
SET @Str = @Delimiter + @Str + @Delimiter

SELECT SUBSTRING(@Str, ID+1, CHARINDEX(@Delimiter, @Str, ID+1) - ID-1) SplitedString
FROM dbo.Tally 
WHERE ID < LEN(@Str)
AND SUBSTRING(@Str, ID, 1) = @Delimiter
 

Here is the output: