Showing posts with label sql query. Show all posts
Showing posts with label sql query. Show all posts

Sunday, 5 May 2013

Using Pivot Operator in SQL- Server

PIVOT can be used to generate cross tabulation reports to summarize data as it creates a more easy understandable data in a user friendly format.
PIVOT rotates a table-valued expression by turning the unique values from one column in the expression into multiple columns in the output
i.e it rotates a rows to columns and aggregations where they are required on any remaining column values that are wanted in the final output.

Syntax for the PIVOT operator:

SELECT <non-pivoted column>,
    [ pivoted column] AS <column name>,
    [ pivoted column] AS <column name>,
    ...
    [ pivoted column] AS <column name>
FROM
    (<SELECT query that produces the data>)
    AS <alias for the source query>
PIVOT
(
    <aggregation function>(column)
FOR
[<column that contains the values that will become column headers>]
    IN ( [pivoted column], [pivoted column],
    ... [pivoted column])
) AS <alias for the pivot table>
[ORDER BY clause];

Example:
Suppose  in the database table "CREDITCARD" , there are two columns [CARDTYPE] and [EXPYEAR] that hold the data for the cardtype and the expiration year of
the credit card . A report on count of the no of credit card expired in year 2007, 2008 and 2009 of each card type is needed. In this case the query will be
 SELECT CARDTYPE, [2007] AS EXP_IN_2007, [2008] AS EXP_IN_2008, [2009] AS EXP_IN_2009

 FROM

 (SELECT CARDtYPE,EXPYEAR FROM  CREDITCARD)
 PIVOT
 (COUNT(EXPYEAR) FOR EXPYEAR IN ([2007],[2008],[2009]))

 ORDER BY CARDTYPE


Here is the number of records in the table
pivot2
And here is the report acording to our requirement
pivot1

Thursday, 11 October 2012

How same Query using SQL , LINQ and Lambda

If you are already working with SQL and are familiar with SQL queries then you may find you at time are thinking of converting SQL syntax to LINQ syntax when writing LINQ. Following cheat sheet should help you with some of the common queries

SQL
LINQ
Lambda
SELECT *
FROM HumanResources.Employee
from e in Employees
select e
Employees
   .Select (e => e)
SELECT e.LoginID, e.JobTitle
FROM HumanResources.Employee AS e
from e in Employees
select new {e.LoginID, e.JobTitle}
Employees
   .Select (
      e =>
         new 
         {
            LoginID = e.LoginID,
            JobTitle = e.JobTitle
         }
   )
SELECT e.LoginID AS ID, e.JobTitle AS Title
FROM HumanResources.Employee AS e
from e in Employees
select new {ID = e.LoginID, Title = e.JobTitle}
Employees
   .Select (
      e =>
         new 
         {
            ID = e.LoginID,
            Title = e.JobTitle
         }
   )
SELECT DISTINCT e.JobTitle
FROM HumanResources.Employee AS e
(from e in Employees
select e.JobTitle).Distinct()
Employees
   .Select (e => e.JobTitle)
   .Distinct ()
SELECT e.*
FROM HumanResources.Employee AS e
WHERE e.LoginID = ‘test’
from e in Employees
where e.LoginID == "test"
select e
Employees
   .Where (e => (e.LoginID == "test"))
SELECT e.*
FROM HumanResources.Employee AS e
WHERE e.LoginID = ‘test’ AND e.SalariedFlag = 1
from e in Employees
where e.LoginID == "test" && e.SalariedFlag
select e
Employees
   .Where (e => ((e.LoginID == "test") && e.SalariedFlag))
SELECT e.*
FROM HumanResources.Employee AS e
WHERE e.VacationHours >= 2 AND e.VacationHours <= 10
from e in Employees
where e.VacationHours >= 2 && e.VacationHours <= 10
select e
Employees
   .Where (e => (((Int32)(e.VacationHours) >= 2) && ((Int32)(e.VacationHours) <= 10)))
SELECT e.*
FROM HumanResources.Employee AS e
ORDER BY e.NationalIDNumber
from e in Employees
orderby e.NationalIDNumber
select e
Employees
   .OrderBy (e => e.NationalIDNumber)
SELECT e.*
FROM HumanResources.Employee AS e
ORDER BY e.HireDate DESC, e.NationalIDNumber
from e in Employees
orderby e.HireDate descending, e.NationalIDNumber
select e
Employees
   .OrderByDescending (e => e.HireDate)
   .ThenBy (e => e.NationalIDNumber)
SELECT e.*
FROM HumanResources.Employee AS e
WHERE e.JobTitle LIKE ‘Vice%’ OR SUBSTRING(e.JobTitle, 0, 3) = ‘Pro’
from e in Employees
where e.JobTitle.StartsWith("Vice") || e.JobTitle.Substring(0, 3) == "Pro"
select e
Employees
   .Where (e => (e.JobTitle.StartsWith ("Vice") || (e.JobTitle.Substring (0, 3) == "Pro")))
SELECT SUM(e.VacationHours)
FROM HumanResources.Employee AS e

Employees.Sum(e => e.VacationHours);
SELECT COUNT(*)
FROM HumanResources.Employee AS e

Employees.Count();
SELECT SUM(e.VacationHours) AS TotalVacations, e.JobTitle
FROM HumanResources.Employee AS e
GROUP BY e.JobTitle
from e in Employees
group e by e.JobTitle into g
select new {JobTitle = g.Key, TotalVacations = g.Sum(e => e.VacationHours)}
Employees
   .GroupBy (e => e.JobTitle)
   .Select (
      g =>
         new 
         {
            JobTitle = g.Key,
            TotalVacations = g.Sum (e => (Int32)(e.VacationHours))
         }
   )
SELECT e.JobTitle, SUM(e.VacationHours) AS TotalVacations
FROM HumanResources.Employee AS e
GROUP BY e.JobTitle
HAVING e.COUNT(*) > 2
from e in Employees
group e by e.JobTitle into g
where g.Count() > 2
select new {JobTitle = g.Key, TotalVacations = g.Sum(e => e.VacationHours)}
Employees
   .GroupBy (e => e.JobTitle)
   .Where (g => (g.Count () > 2))
   .Select (
      g =>
         new 
         {
            JobTitle = g.Key,
            TotalVacations = g.Sum (e => (Int32)(e.VacationHours))
         }
   )
SELECT *
FROM Production.Product AS p, Production.ProductReview AS pr
from p in Products
from pr in ProductReviews
select new {p, pr}
Products
   .SelectMany (
      p => ProductReviews,
      (p, pr) =>
         new 
         {
            p = p,
            pr = pr
         }
   )
SELECT *
FROM Production.Product AS p
INNER JOIN Production.ProductReview AS pr ON p.ProductID = pr.ProductID
from p in Products
join pr in ProductReviews on p.ProductID equals pr.ProductID
select new {p, pr}
Products
   .Join (
      ProductReviews,
      p => p.ProductID,
      pr => pr.ProductID,
      (p, pr) =>
         new 
         {
            p = p,
            pr = pr
         }
   )
SELECT *
FROM Production.Product AS p
INNER JOIN Production.ProductCostHistory AS pch ON p.ProductID = pch.ProductID AND p.SellStartDate = pch.StartDate
from p in Products
join pch in ProductCostHistories on new {p.ProductID, StartDate = p.SellStartDate} equals new {pch.ProductID, StartDate = pch.StartDate}
select new {p, pch}
Products
   .Join (
      ProductCostHistories,
      p =>
         new 
         {
            ProductID = p.ProductID,
            StartDate = p.SellStartDate
         },
      pch =>
         new 
         {
            ProductID = pch.ProductID,
            StartDate = pch.StartDate
         },
      (p, pch) =>
         new 
         {
            p = p,
            pch = pch
         }
   )
SELECT *
FROM Production.Product AS p
LEFT OUTER JOIN Production.ProductReview AS pr ON p.ProductID = pr.ProductID
from p in Products
join pr in ProductReviews on p.ProductID equals pr.ProductID
into prodrev
select new {p, prodrev}
Products
   .GroupJoin (
      ProductReviews,
      p => p.ProductID,
      pr => pr.ProductID,
      (p, prodrev) =>
         new 
         {
            p = p,
            prodrev = prodrev
         }
   )
SELECT p.ProductID AS ID
FROM Production.Product AS p
UNION
SELECT pr.ProductReviewID
FROM Production.ProductReview AS pr
(from p in Products
select new {ID = p.ProductID}).Union(
from pr in ProductReviews
select new {ID = pr.ProductReviewID})
Products
   .Select (
      p =>
         new 
         {
            ID = p.ProductID
         }
   )
   .Union (
      ProductReviews
         .Select (
            pr =>
               new 
               {
                  ID = pr.ProductReviewID
               }
         )
   )
SELECT TOP (10) *
FROM Production.Product AS p
WHERE p.StandardCost < 100
(from p in Products
where p.StandardCost < 100
select p).Take(10)
Products
   .Where (p => (p.StandardCost < 100))
   .Take (10)
SELECT *
FROM [Production].[Product] AS p
WHERE p.ProductID IN(
    SELECT pr.ProductID
    FROM [Production].[ProductReview] AS [pr]
    WHERE pr.[Rating] = 5
    )
from p in Products
where (from pr in ProductReviews
where pr.Rating == 5
select pr.ProductID).Contains(p.ProductID)
select p
Products
   .Where (
      p =>
         ProductReviews
            .Where (pr => (pr.Rating == 5))
            .Select (pr => pr.ProductID)
            .Contains (p.ProductID)
   )

Also, here is an excellent LINQ query comprehension diagram http://www.albahari.com/nutshell/linqsyntax.emf

Friday, 5 October 2012

Comparing DateTime Column in SQL Server

Introduction: This article addresses the following issues:

1) Time also stores in DateTime column therefore Time is also required while comparing
2) How to extract only Date (excluding the Time) from DateTime column

Level: Beginner

Knowledge Required:
  • T-SQL
  • SQL Server 2005/2008/2012
Description:
While working with Database we usually face an issue where we need to compare the given Date with SQL Server DateTime column. For example:

SELECT * FROM Orders WHERE Order_Date = '5-May-2008'

As we can see in above example we are comparing our date i.e. '5-May-2008' with the DateTime column Order_Date. But it is NOT sure that all the Rows of 5-May-2008 will be returned. This is because Time also stores here. So if we look into the Table we will find that,

Order_Date = '5-May-2008 10:30'
Order_Date = '5-May-2008 11:00'
Order_Date = '5-May-2008 14:00'

So when we give '5-May-2008' to SQL Server then it automatically converts it into:

Order_Date = '5-May-2008 12:00'

Therefore this date will NOT be equal to any of the dates above.

There are several techniques to handle this issue, I will discuss some here:

1) Compare all the 3 parts (day, month, year)
2) Convert both (the given Date and the DateTime Column) into some predefined format using CONVERT function
3) Use Date Range

1) Compare all the 3 parts:
Example:

DECLARE @Given_Date DateTime;

SET @Given_Date = '5-May-2008 12:00';

SELECT *
FROM Orders 
WHERE   Day(Order_Date) = Day(@Given_Date) AND
        Month(Order_Date) = Month(@Given_Date) AND
        Year(Order_Date) = Year(@Given_Date);


2) Convert both (the given Date and the DateTime Column) into some predefined format using CONVERT function:
Example:

DECLARE @Given_Date DateTime;

SET @Given_Date = '5-May-2008 12:00';

SELECT *
FROM Orders 
WHERE   CONVERT(varchar(100), Order_Date, 112) = CONVERT(varchar(100), @Given_Date, 112);

Note that CONVERT function will work as:
Print CONVERT(varchar(100), CAST('5-May-2008' AS DateTime), 112);

Output:

20080505

But we have limitation i.e. cannot use '<' and '>' operators here.

3) Use Date Range
Example:

DECLARE @Given_Date DateTime;
DECLARE @Start_Date DateTime;
DECLARE @End_Date DateTime;

SET @Given_Date = '5-May-2008 12:00';
SET @Start_Date = CAST(CAST(Day(@Given_Date) As varchar(100)) + '-' + DateName(mm, @Given_Date) + '-' + CAST(Year(@Given_Date) As varchar(100)) As DateTime);
SET @End_Date = CAST(CAST(Day(@Given_Date) As varchar(100)) + '-' + DateName(mm, @Given_Date) + '-' + CAST(Year(@Given_Date) As varchar(100)) + ' 23:59:59' As DateTime);

SELECT *
FROM Order
WHERE Order_Date Between @Start_Date AND @End_Date;

In my opinion the last example is the fastest, since in all the previous examples SQL Server has to perform some extraction/conversion each time while extracting the Rows. But in the last method SQL Server will convert the Given Date only once, and in SELECT statement each time it is comparing the Dates, which is obviously faster than comparing a Date after converting it into VarChar or comparing each part of Date. Also in previous 2 methods we have limitation i.e. we cannot use the Range.


The following table summarizes these six data types format, range, accuracy, and storage size in bytes, and is taken from the Date and Time Data Types and Functions technical documentation.


Data type Format Range Accuracy Storage size (bytes)
time hh:mm:ss[.nnnnnnn] 00:00:00.0000000 through 23:59:59.9999999 100 nanoseconds 3 to 5
date YYYY-MM-DD 0001-01-01 through 9999-12-31 1 day 3
smalldatetime YYYY-MM-DD hh:mm:ss 1900-01-01 through 2079-06-06 1 minute 4
datetime YYYY-MM-DD hh:mm:ss[.nnn] 1753-01-01 through 9999-12-31 0.00333 second 8
datetime2 YYYY-MM-DD hh:mm:ss[.nnnnnnn] 0001-01-01 00:00:00.0000000 through 9999-12-31 23:59:59.9999999 100 nanoseconds 6 to 8
datetimeoffset YYYY-MM-DD hh:mm:ss[.nnnnnnn] [+|-]hh:mm 0001-01-01 00:00:00.0000000 through 9999-12-31 23:59:59.9999999 (in UTC) 100 nanoseconds 8 to 10
 

Note: The time, datetime2, and datetimeoffset data types' storage spaces are between a range because when you use the data type you can specify the precision.