Saturday, November 22, 2008

Date Formats In SQL SERVER.

In this post I will try to explain how to convert date in required format.

As we know by default (U.S. English) Sql Server shows dates in mdy.
i.e.
2008-11-22 14:02:12.513
OR
11/22/2008 2:02:00 PM
And so many times you wants the date in dd/mm/yy or dd Mon yyyy or any other format you want.

The function used by sql server to convert the dates in required format is CONVERT. Which I personaly find more easy to use compare to to_date used by Oracle or other fuctions used by other DBMS.

Syntax for the CONVERT is
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
Where data_type can be either string datatype (char/ varchar) or datetime.
And Style in nothing but numbers in 1st 2 columns in following table .




1. Now for example If I want the date in "mon dd yyyy"
I will choose the style as 100 (from the above table)

SELECT CONVERT( varchar(50), date_column, 100)
FROM table_name
go;

e.g.
SELECT CONVERT(varchar(50), GETDATE(), 100)
GO
/* output
Nov 22 2008 2:21PM
*/
2. Or if I want mm/dd/yyyy I will select style 101

SELECT CONVERT(varchar(50), GETDATE(), 101)
GO
/* output
11/22/2008

*/

Now if instead of 2008 if I want only 08 I will select style from 1st column instead of column 2 which is style 1

SELECT CONVERT(varchar(50), GETDATE(), 1)
GO
/* output
11/22/08
*/

So if you want the century part in year (2008, 2009)select style from column 2 (100, 101, 102) or if you want only 2 digits of year (08, 09) select style from 1st column (1, 2, 3).

For more on CONVERT see
CAST and CONVERT (Transact-SQL) Books Online


- Mangal Pardeshi.

Sunday, October 5, 2008

Difference between ROW_NUMBER, RANK and DENSE_RANK

What is the Difference between ROW_NUMBER, RANK and DENSE_RANK? Which one to use?
This is very common question in the minds of SQL newbie's.
Lets take 1 simple example to understand the difference between 3.

First lets create some sample data :

-- create table
CREATE TABLE Salaries
(
Names VARCHAR(1),
SalarY INT
)
GO
-- insert data
INSERT INTO Salaries SELECT
'A',5000 UNION ALL SELECT
'B',5000 UNION ALL SELECT
'C',3000 UNION ALL SELECT
'D',4000 UNION ALL SELECT
'E',6000 UNION ALL SELECT
'F',10000
GO
-- Test the data
SELECT Names, Salary
FROM Salaries


Now lets query the table to get the salaries of all employees with their salary in descending order.
For that I'll write a query like this :

SELECT names
        , salary
        ,row_number () OVER (ORDER BY salary DESC) as ROW_NUMBER
        ,rank () OVER (ORDER BY salary DESC) as RANK
        ,dense_rank () OVER (ORDER BY salary DESC) as DENSE_RANK
FROM salaries


>>Output
NAMES SALARY ROW_NUMBER RANK DENSE_RANK
F 10000 1 1 1
E 6000 2 2 2
A 5000 3 3 3
B 5000 4 3 3
D 4000 5 5 4
C 3000 6 6 5

Interesting Names in the result are employee A, B and D. 
Row_number assign different number to them.
Rank and Dense_rank both assign same rank to A and B.
But interesting thing is what RANK and DENSE_RANK assign to next row?
Rank assign 5 to the next row, while dense_rank assign 4.

The numbers returned by the DENSE_RANK function do not have gaps and always have consecutive ranks.  The RANK function does not always return consecutive integers.  The ORDER BY clause determines the sequence in which the rows are assigned their unique ROW_NUMBER within a specified partition.

So question is which one to use?
Its all depends on your requirement and business rule you are following.
1. Row_number to be used only when you just want to have serial number on result set. It is not as intelligent as RANK and DENSE_RANK.
2. Choice between RANK and DENSE_RANK depends on business rule you are following. Rank leaves the gaps between number when it sees common values in 2 or more rows. DENSE_RANK don't leave any gaps between ranks.
So while assigning the next rank to the row RANK will consider the total count of rows before that row and DESNE_RANK will just give next rank according to the value.
So If you are selecting employee’s rank according to their salaries you should be using DENSE_RANK and if you are ranking students according to there marks you should be using RANK(Though it is not mandatory, depends on your requirement.)

Mangal Pardeshi

SQL MVP

Thursday, October 2, 2008