SQLvariations: SQL Server, a little PowerShell, maybe some Hyper-V Rotating Header Image

T-SQL

Get-Sales | Out-Map = T-SQL Tuesday #005 – Reporting

For this month’s T-SQL Tuesday I thought I’d go with something useful that I’ve been meaning to blog about for weeks now.  While listening to the PowerScripting Podcast a few month’s back I heard about a product that sounded really cool for simple data visualization and quickly showing people just how powerful PowerShell is.  Now to get this to work using all the code on the screen you’ll at least have to download the trial version of of the Power Gadgets however even without the method I describe is important if you’re new to this type of reporting (desktop gadgets).

Turns out this little piece of software had even more packed into it than I was hoping for.  I needed a piece of software that could allow me to pipe data to it to display it in a desktop gadget as a list.

Before I show you how to setup this quick-and-easy tool to create desktop gadgets I want to issue a warning against setting up this type of thing directly against your production database; read all the way through or don’t blame me when you bring your production environment down.

image

What you want to do (at the very least) is to have all of the gadgets that you deploy read from a central location where they only have to scoop up the results of the query that you’re trying to report on, and not 400 gadgets running the query itself.  An easy way to accomplish this would be to run the query in an Agent Job against your production environment (assuming that you don’t have a live reporting copy) and deposit those results in a table.  Let’s see if we can step through an example with the AdventureWorks database.

If this below were your query to show your sales for today…

SELECT SUM(SOD.OrderQty) AS OrderQty, s.StateProvinceCode
  FROM Sales.SalesOrderHeader SOH
 INNER JOIN Sales.SalesOrderDetail SOD
    ON SOH.SalesOrderID = SOD.SalesOrderID
  JOIN Production.Product P
    ON SOD.ProductID = P.ProductID
  JOIN Person.Address A
    ON SOH.BillToAddressID = A.AddressID
  JOIN Person.StateProvince S
    ON A.StateProvinceID = S.StateProvinceID
 WHERE SOH.OrderDate = ’2001-07-01 00:00:00.000′ –<—This would get GETDATE() or something
 GROUP BY S.StateProvinceCode

…you would really want to create an Agent Job to load that into a table and select off of the table.  For simplicity we’ll leave out the job and just use the queries.

/* <Do this part only one time>*/

USE [AdventureWorks]

GO

CREATE SCHEMA [Report] AUTHORIZATION [dbo]

GO

CREATE TABLE [Report].[TodaysSalesOrderByState](

[OrderQty] [int] NULL,

[StateProvinceCode] [nchar](3) NOT NULL,

[LastLoadTime] DATETIME NOT NULL CONSTRAINT [DF_LastLoadTime] DEFAULT GETDATE()

) ON [PRIMARY]

/* </Do this part only one time>*/

Then this…

/* <This is the part that would eventually go into an agent job, along with a delete statement before it that was in the same transaction>*/

 INSERT INTO Report.TodaysSalesOrderByState (

[OrderQty],

[StateProvinceCode])

SELECT SUM(SOD.OrderQty) AS OrderQty, s.StateProvinceCode

  FROM Sales.SalesOrderHeader SOH

 INNER JOIN Sales.SalesOrderDetail SOD

    ON SOH.SalesOrderID = SOD.SalesOrderID

  JOIN Production.Product P

    ON SOD.ProductID = P.ProductID

  JOIN Person.Address A

    ON SOH.BillToAddressID = A.AddressID

  JOIN Person.StateProvince S

    ON A.StateProvinceID = S.StateProvinceID

 WHERE SOH.OrderDate = ’2001-07-01 00:00:00.000′ –<—This would get GETDATE() or something

 GROUP BY S.StateProvinceCode

/* </This is the part that would eventually go into an agent job>*/

Now you’ll want to create a stored proc that will be used to call the report data.  It will also make creating the report nice and clean.

CREATE PROCEDURE [dbo].[rp_MapThat]
AS 

SELECT [OrderQty]
      ,[StateProvinceCode] AS ‘State’
  FROM [AdventureWorks].[Report].[TodaysSalesOrderByState]
GO

After that all you have to do is to go ahead and create the gadget using this little script:

#Go ahead and add the SQL Snapins
add-pssnapin SqlServerCmdletSnapin100
add-pssnapin SqlServerProviderSnapin100
#add the Gadgets Snapin
add-pssnapin PowerGadgets            

invoke-sqlcmd -query "EXEC dbo.rp_MapThat" -database AdventureWorks -serverinstance WIN7\KILIMANJARO | out-map -values OrderQty -label State -title "CountByState" -refresh 0:1:0

 

And now you’ve got a gadget prototype.  I’m sure you can figure out how to turn it into an operational gadget for your company.

 

 

LiveJournal Tags:

Free Training from PASS Virtual Chapters

We’ve got some great free training coming up this week from the AppDev and DBA Virtual Chapters of PASS.  I personally am really looking forward to “SQL Server Consolidation: How to decide on the right approach (between DB, VMs, Instance)?”  It sounds like a really good session to me :-)   Please note that the “Defensive Programming’’ session has been timed for our international members.  We’ll have more news on upcoming session probably early next week so please check back soon.

PASS AppDev VC Presents: Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server
Date: Start Time:    End Time:    Time Zone: Add to your calendar
1/26/2010 8:00 AM 9:00 AM (GMT-05:00) Eastern Time (US & Canada) Export to Calendar

Event Description:
This is a deep dive developer session that explores error handling in SQL Server. The session focuses on core error handling areas such as understanding the anatomy of errors, detecting errors in TSQL and best practices for error handling and defensive programming in Microsoft SQL Server.

Jacob Sebastian is a SQL Server MVP and is working with SQL Server for over 11 years. He is a Moderator of MSDN / TechNet Forums, Regional Mentor for PASS Asia and a regular columnist at SQL Server Central. He is the president of Ahmedabad SQL Server User Group and a regular speaker in SQL Server events in India and USA. Jacob is the author of “The Art of XSD – SQL Server XML Schema Collections”, a contributing author in “SQL Server 2008 Bible” and is currently writing a book in FILESTREAM. He blogs at BeyondRelational [http://beyondrelational.com/blogs/jacob/]

How Do I View the Presentation?
Follow the link and join the LiveMeeting.
Audio: Audio will be provided via computer speakers.

PASS DBA VC Presents: SQL Server Consolidation : how to decide on the right approach (between DB, VMs, Instance)?
Date: Start Time:    End Time:    Time Zone:
1/27/2010 12:00 PM 1:00 PM (GMT-05:00) Eastern Time (US & Canada)

Event Description:
This session will focus on helping to choose between using a virtualization, instance, or database consolidation option. We will highlight a few of the key areas to consider as well as some of the important differentiators to keep in mind. We will provide a decision tree to help guide administrators through the process of selecting a consolidation option. Objectives: 1. Provide administrators with a decision tree for choosing a consolidation option 2. Highlight key decision criteria and differentiators 3. Discuss hardware considerations 4. Highlighting customer case studies and deployment scenarios

Sung Hsueh of Microsoft will be speaking about how to choose between using a virtualization, instance, or database consolidation option. We will highlight a few of the key areas to consider as well as some of the important differentiators to keep in mind. We will provide a decision tree to help guide administrators through the process of selecting a consolidation option.

Location: Online, via Live Meeting
[https://www.livemeeting.com/cc/usergroups/join?id=4HG9C2&role=attend]

And as always, please feel free to leave a comment here if you would like a topic presented or if you would like to do a presentation.

Lunch-n-Learn #01: SQL Server 2005 Features

Yesterday I did a quick Lunch-n-Learn here at my company on a few SQL Server 2005 features and this post is just a follow-up to remind everyone what we saw and where you can find those features.  I will try to still make this useful for those of you who didn’t attend.

0:  To make any of these code examples work please download and install the Sample Databases for SQL Server.  (Don’t worry, they’re pretty small.)

  1. The first thing that you folks saw was the intelli-sense where as I was typing the name of a table and SQL Server Management Studio (SSMS) was finishing the table name for me.  That was the only SQL Server 2008 exclusive feature that you saw in the entire session.  You can only see this if you have the SSMS 2008 client pointed to a SQL 2008 db.
  2. I showed you guys how to find out the name of every table and column of the db that you are in using the system views:
    SELECT *
    FROM INFORMATION_SCHEMA.TABLES
  3. SELECT *
    FROM INFORMATION_SCHEMA.COLUMNS

  4. Ticks!  How did this apostrophe get into our db?  And how do we get it out?
    SELECT  [Comments] ,[ProductReviewID] ,[ProductID] ,[ReviewerName] ,[ReviewDate] ,[EmailAddress] ,[Rating] ,[ModifiedDate]
      FROM [AdventureWorks].[Production].[ProductReview]
  5. Well you just use 2 ticks to insert a single tick.  Said again, you use “’’” to insert “” into SQL. Here’s an example from the AdventureWorks database:
    SET IDENTITY_INSERT [Production].[ProductReview] ON
    INSERT [Production].[ProductReview] ([ProductReviewID], [ProductID], [ReviewerName], [ReviewDate], [EmailAddress], [Rating], [Comments], [ModifiedDate])
    VALUES
    (6, 709, ‘John Smith’, CAST(0×0000941800000000 AS DateTime), “>‘john@fourthcoffee.com’, 5
    , ‘I can”t believe I”m singing the praises of a pair of socks, but I just came back from a grueling
    3-day ride and these socks really helped make the trip a blast. They”re lightweight yet really cushioned my feet all day.
    The reinforced toe is nearly bullet-proof and I didn”t experience any problems with rubbing or blisters like I have with
    other brands. I know it sounds silly, but it”s always the little stuff (like comfortable feet) that makes or breaks a long trip.
    I won”t go on another trip without them!’
    , CAST(0×0000941800000000 AS DateTime))
    SET IDENTITY_INSERT [Production].[ProductReview] OFF

    And we can get it out like this:
    UPDATE [Production].[ProductReview]
       SET Comments = REPLACE(Comments, ””, )
     WHERE ProductReviewID = 6

  6. To make your keyboard as useful as mine what you do is open up SSMS click on Tool > Options > Environment > Keyboard >and add the commands that you would like the corresponding shortcut key to execute.
    image
  7. What Exactly is XACT_ABORT?  When XACT_ABORT is ON SQL Server will stop and roll back the transaction as soon as it hits an error; it won’t continue processing all the way to the end.  “When SET XACT_ABORT is OFF, in some cases only the Transact-SQL statement that raised the error is rolled back and the transaction continues processing.”
    Use this script to see it work for yourself.
  8. The next feature that I showed you was how you can create an Identity Column for the data you are  selecting without having to insert the data into a table by using the ROW_NUMBER() function.  I mentioned several other features along with that one and I will demo those features in our next Lunch-n-Learn.  In the meantime here’s a script that will show you it do 4 different row numbers on 4 different fields all at the same time.
    /* SQL Purists: please don’t freak out at this script, I’m just showing functionality*/
    SELECT TOP 500 *
                 ROW_NUMBER
    () OVER (ORDER BY AvgCPUTime DESC) AS 'AVG Time Rank'
          
    ,     ROW_NUMBER() OVER (ORDER BY total_cpu_time DESC) AS 'Total CPU Rank'
          
    ,     ROW_NUMBER() OVER (ORDER BY total_duration_time DESC) AS 'Total Duration Rank'
          
    ,     ROW_NUMBER() OVER (ORDER BY total_execution_count DESC) AS 'Total Executions Rank'
          
    , a.TEXT AS 'StatementText'
          
    , a.total_cpu_time
          
    , a.total_execution_count
          
    , a.total_duration_time
          
    , a.AvgCPUTime
          
    , a.number_of_statements
          
    , a.plan_handle
          
    , SUBSTRING(a.TEXT, 1, 100) AS 'hundy', a.name
      
    FROM (
          
    SELECT
                
    sql_text.TEXT,
              
    SUM(qs.total_worker_time) AS total_cpu_time,�
              
    SUM(qs.total_elapsed_time) AS total_duration_time,�
              
    SUM(qs.execution_count) AS total_execution_count,
              
    SUM(qs.total_worker_time) / SUM(qs.execution_count) AS AvgCPUTime,
              
    COUNT(*) AS  number_of_statements,�
              
    qs.plan_handle , db.name
          
    FROM�
              
    sys.dm_exec_query_stats qs
              
    CROSS apply sys.dm_exec_sql_text(sql_handle) AS sql_text
          
    LEFT OUTER JOIN sys.databases db
            
    ON sql_text.dbid = db.database_id
          
    --WHERE dbid = 10
          
    GROUP BY sql_text.TEXT,
          
    qs.plan_handle , db.name
    )a
    ORDER BY AvgCPUTime DESC
  9. Comparing which way is better.  To compare how long and how much data was needed to satisfy two different queries you can just click on the Include Client Statistics button before you run the first query and it will start capturing the statistics for you:
    image
  10. And finally the built-in reports.  To run any of them just Right-Click any database in SSMS Object Explorer and navigate to the report that you want:

That pretty much wraps it up for what we covered yesterday.  I will put some examples together for the Common Table Expressions (CTE), RANK, DENSE_RANK, and NTILE fuctions that I mentioned yesterday so that we can go over them at the next one.  Next Tuesday work good for you?  :-)
If you would like anything else covered you can just email me or comment here.

T-SQL Tuesday #002 A Puzzling Situation: Max Server Memory

Today’s post about changing your Max Server Memory setting is to answer the call from Adam Machanic about Puzzling Situations .

A couple weeks before I headed out to the 2009 PASS Summit I encountered a puzzler of my own. One of our servers issued an alert that it had an extremely low Page Life Expectancy (PLE); like 16. All of the databases on this server had recently migrated from an older 32 bit server with 4 GB of RAM to thier current 64 bit server with 8 GB of RAM. As luck would have it, this was the source of my puzzling situation. When we migrated the dbs we inadvertantly transfered the memory configuration used in their old 32 bit server home. Who made this classic rookie error?? Yours truly. I was doing two server migrations at once and bobbled the checklists.

I rectified the situation by increasing the RAM settings from 3 GB to 6 GB:

sp_configure 'max server memory (MB)', '6144'
RECONFIGURE

MaxRAMBefore

Want to guess what happened when I ran the RECONFIGURE command?

I watched as the perfmon counters immediately went down! Indicating that memory usage had dropped rather than increased.

MaxRAMAfter

As it turns out in SQL Server 2005 (and in SQL Server 2008 as far as I know) when you run RECONFIGURE for anything you dump the procedure cache. So for example if you were to change the setting for ‘”Web Assistant Procedures” you would dump the procedure cache. If you were to change the setting for “fill factor (%)” you would dump the procedure cache.

So beware before you change a configuration setting in your Production environment and run RECONFIGURE.

So there’s my Puzzling Situations for T-SQL Tuesday #002

T-SQL Tuesday Date, Time, tricks with the DateTime Data Type

Adam Machanic told us all about a new craze sweeping the SQL Blogosphere Nation last week and that is T-SQL Tuesdays. Real quick, the way it works is that on Patch-Tuesday everyone who’s got something to say about the topic of the month releases a blog post about it and the “Host” of the topic recaps all of the various blog posts in a blog at their site. OK now onto the topic.

Because I think there might be a few people bolgging about this today I will keep min short-and-sweet and go over 5 main points of the Old-School DateTime data type.

Before I start I want to remind you that DBAs Data Professionals are a little different, a lot of us think in terms of Largest to Smallest unit when we think of DateTime; which makes it into the way that you think of a standard number. Right now it is “200912051505” or “2009-12-05 15:05”

Selecting and aggregating using Styles all of the rows in a table can be a little problematic if you are selecting a date that looks something like this one “2009-12-05 15:05”. One of my favorite ways to get around this is with the CONVERT function and changing it to a VARCHAR and then using a style. Here’s what I usually do.

Run this query in AdventureWorks and you’ll notice that it also pulls in time which might be something that we want to avoid:

SELECT COUNT(*) AS '# of Orders'
 , OrderDate AS 'Order Date'
  FROM Sales.SalesOrderHeader
 GROUP BY OrderDate
 ORDER BY OrderDate
# of Orders Order Date
32 2008-07-28 00:00:00.000
31 2008-07-29 00:00:00.000
23 2008-07-30 00:00:00.000
40 2008-07-31 00:00:00.000

So what I do is CONVERT it to VARCHAR and then add Style 112 to it

SELECT COUNT(*) AS '# of Orders'
 , CONVERT(VARCHAR, OrderDate, 112) AS 'Order Date'
  FROM Sales.SalesOrderHeader
 GROUP BY CONVERT(VARCHAR, OrderDate, 112)
 ORDER BY CONVERT(VARCHAR, OrderDate, 112)
# of Orders Order Date
32 20080728
31 20080729
23 20080730
40 20080731

Now this isn’t overly readable but it sorts great. Another problem with it is that it doesn’t paste into Excel real well. For pasting into Excel and having it quickly recognize it as a DateTime field I use Style 110 but there’s a catch. Style 110 pastes into Excel fine but it doesn’t sort properly so I end up having to keep my Style 112 column so that I can sort on it.

SELECT COUNT(*) AS '# of Orders'
  , CONVERT(VARCHAR, OrderDate, 110) AS 'Order Date'
  , CONVERT(VARCHAR, OrderDate, 112) AS 'Order Sort'
  FROM Sales.SalesOrderHeader
 GROUP BY CONVERT(VARCHAR, OrderDate, 110)
  , CONVERT(VARCHAR, OrderDate, 112)
 ORDER BY CONVERT(VARCHAR, OrderDate, 112)
# of Orders Order Date
32 7/28/2008
31 7/29/2008
23 7/30/2008
40 7/31/2008

Selecting just the time with Style 108 is another trick I have used in the past. As a quick and easy way to extract just the time out of a DateTime field is to CONVERT it to VARCHAR making sure to specify a length of 5. (Now if you also want the seconds you need to make the length 8.)

SELECT GETDATE() AS 'GetDate', CONVERT(VARCHAR(5)
 , GETDATE(), 108) AS 'GetTime'
GetDate GetTime
2009-12-05 17:10:54.430 17:10

And now for my final trick
Selecting the date of the Sunday of the Week (or any recurring day of the week)

Sometimes – especially in Business Intelligence – you want to group data by week but you don’t want to use DATEPART (WK, OrderDate) because that produces a number and you might want something more like an actual date. In this case what I typically do is just use this: DATEADD(DAY, 1-DATEPART(WEEKDAY, OrderDate), OrderDate)
(Now you can pick the Saturday of that week just as easily by swapping out that 1 for a 7.)

SELECT COUNT(*) AS '# of Orders'
 , DATEPART (WK, OrderDate)
 , DATEADD(DAY, 1-DATEPART(WEEKDAY, OrderDate), OrderDate) AS 'Sunday of the Week'
 , DATEPART(WEEKDAY, OrderDate) AS 'Day# of Week'
 , CONVERT(VARCHAR, OrderDate, 112) AS 'Order Date'
  FROM Sales.SalesOrderHeader
 GROUP BY DATEPART (WK, OrderDate)
 , CONVERT(VARCHAR, OrderDate, 112)
 , DATEADD(DAY, 1-DATEPART(WEEKDAY, OrderDate), OrderDate)
 , DATEPART(WEEKDAY, OrderDate)
 ORDER BY CONVERT(VARCHAR, OrderDate, 112)
# of Orders Sunday of the Week Day# of Week Order Date
24 2008-07-20 00:00:00.000 6 20080725
32 2008-07-20 00:00:00.000 7 20080726
29 2008-07-27 00:00:00.000 1 20080727
32 2008-07-27 00:00:00.000 2 20080728
31 2008-07-27 00:00:00.000 3 20080729
23 2008-07-27 00:00:00.000 4 20080730
40 2008-07-27 00:00:00.000 5 20080731

You can check out the rest of the blogs for this T-SQL Tuesday topic right here: http://sqlblog.com/blogs/adam_machanic/archive/2009/12/09/t-sql-tuesday-001-the-roundup.aspx or do a search on Twitter and look for the hash #TSQL2sDay.
I hope this helps a few people out, as always if you have any questions please comment.
TSQL2sDay