Author: way0utwest

  • Pluralsight is Amazing

    I used to work for a digital learning company early in the modern Internet. We were ahead of our time and struggled to sell online learning at the turn of the millennium. Bandwidth limitations held back video courses from widescale adoption. I moved on when the company folded, but I’ve watched other companies start to build and grow video training across the years. One of them that I’ve been most impressed with is Pluralsight. In fact, I very much appreciate their customer service.

    I try to make time every week to watch something. I don’t always get to any bits of learning, which is the way things go. Life is busy, and some days I don’t have the mental energy. I do try to download a course or two to my phone for long plane rides and other travel. I’ve even had a few modules playing on long drives or in my headphones while skiing. Of course, I can’t watch the screen during those events, but I can listen and try to learn something on the go. I’ve even whiled away sessions on the stationary bike with a Pluralsight course playing in front of me. It’s not deep learning, but it’s a way of looking at something that I find interesting. I often will go back and try a bit of code later.

    I don’t focus too tightly on SQL Server with Pluralsight as I get plenty of that elsewhere, but sometimes I use their courses for investigation into other areas. I’ve listened to Chef and Puppet courses, C#, ASP MVC, Python, and more. I don’t always use the skills directly, but a little learning does help me understand the larger view of how technology works. I’ve found throughout my career that having some good general knowledge in various areas helps me troubleshoot and understand the larger picture, often helping me find an issue in a complex system quicker. I also get ideas on why I might consider some other type of technology as a way of improving an application in the future.

    I certainly hope that most of you continue to come to SQLServerCentral to get ideas, learn something, and get questions answered. My mission with this site is to help others become better SQL Server professionals. We may add some video to go with our written work, and certainly I think we could improve some assessments and testing. If there are areas you’d like to see more content, let us know.

    However, we can’t do what Pluralsight does with their long courses and variety of topics. If you get the chance, or have a subscription, check them out. They provide a great learning resource that I’d recommend.

    Steve Jones

    The Voice of the DBA Podcast

    Listen to the MP3 Audio ( 3.7MB) podcast or subscribe to the feed at iTunes and Libsyn.

  • Can Data Save the World?

    Years ago I read one of the Freakonomics books. It was an interesting look at how we might examine our world in unexpected ways, using lots of data. While I didn’t always agree with the conclusions of the authors in different areas, I did find the idea of using data to probe and examine for patterns in our world to be fascinating.

    Recently I caught a podcast with the authors, and the opening question caught my eye. It was “can data save the world?”, and I was hooked, needing to stop and listen to the episode. That’s because I think data is the most important asset in the world today, and data is what really powers all the software we have. We need data, and we need to ensure our data has a high level of quality and integrity in order to glean information from all those bits and bytes to get value from software. Certainly software matters, but data, to me, is more important.

    The authors’ position is interesting in that they see data as an important part of analyzing data. The type of data, industry, organization, etc. doesn’t matter, but the data also isn’t necessarily enough to change someone’s mind or convince them of an argument. There needs to be a story as well, which requires a different skill from that needed for analyzing data. I do think that often the way in which we present an analysis can be just as important as the data. Perhaps even more so.

    What I do find interesting in the podcast is that younger companies (and people) are willing to embrace more data driven approaches. I see that often. There have been no shortage of clients in my career that were sure they knew the answer to some question about their business job without referring to any data analysis. They trusted their experience. Even if there was data that might show their conclusions were slightly erroneous, they often didn’t want to change their decision or conclusion.

    Humans are creatures of habit. Even those of us that embrace some change will find that we like change in some parts of our lives, but not others. If someone has had success in their career without using data to support or alter their opinions, it can be hard to get them to change. I wish I had a good method for convincing people to get started using more data, but really I think that the best idea is to find a different person to convince. If you can do so, and produce real results, then you may be able to go back to the first person and show them some evidence.

    The one part of the podcast that I wish turned out different is at the end, where the authors note there isn’t a good way to teach someone how to analyze data and tell a story. They thought about creating their own curriculum, but gave up. It’s too much work, and apparently they weren’t sure they could do a good job.

    They imply this is harder than teaching someone to program, which is disappointing as we have lots of programmers that need help as well. If we can’t teach programmers at any scale, what does that mean for data scientists? The one part I would agree with them on is that data science is a great area to move towards your career if you have the talent.

    Steve Jones

    The Voice of the DBA Podcast

    Listen to the MP3 Audio ( 4.3MB) podcast or subscribe to the feed at iTunes and Libsyn.

  • SQL Prompt Gets Even Better

    SQL Prompt v9 came out recently, and just when you thought they couldn’t make it better, they found a way. If you click the menu for SQL Prompt, you’ll see a couple new items.

    2017-11-29 14_55_40-SQLQuery2.sql - (local)_SQL2016.AdventureWorks2014 (PLATO_Steve (66)) - Microsof

    Code Analysis!!! Finally, a first step towards some sort of better analysis of code. These are a set of rules from our SQL Code Guard acquisition and we’ve integrated these into Prompt. Now you’ll get some green squiggly’s to alert you to potential issues.

    For example, I get two in this short, poorly written code. The first item is a TOP without an ORDER BY, which usually isn’t a good thing.

    2017-11-29 14_59_07-SQLQuery2.sql - (local)_SQL2016.AdventureWorks2014 (PLATO_Steve (66))_ - Microso

    The second item is one of those that I would like to put in all CAPs for developers. No asterisks.

    2017-11-29 14_59_11-SQLQuery2.sql - (local)_SQL2016.AdventureWorks2014 (PLATO_Steve (66))_ - Microso

    Right now there are a set of static rules, but we are working to add more and allow you to customize these items. We’re also looking for feedback on how you might like to apply or surface these rules to your staff. Please, if you have comments or questions, ask at the Redgate Hub.

    For now, you can disable analysis, or disable selected rules. Click the Manage link, and you’ll see a list of rules, which you can turn off as needed.

    2017-11-29 14_55_51-Sql Prompt - Code analysis rules

    Static analysis of SQL code has a long way to go, but I am looking forward to seeing more improvements appear in SQL Prompt and our other products over time.

  • Testing a Birthday Month Query

    I ran across a post from a tester, wondering  how to write a query for birthday months. This makes sense, as I’m sure some businesses want to notify or track customers that have birthdays this month and give them something.

    The post was good, with DDL and test data, and ignoring the discussion about database design, how would you test htis? If you look through the test data, surely you might decide to check for Jan, or Feb, etc., but are you use as the query might change that you’re checking everything?

    This is where testing can help. I’d start with a simple test. One that uses some data and checks that nothing is returned.

    CREATE OR ALTER PROCEDURE tTSQLTests.[test birthday queries for a Jan with no birthdays in range]
    /*
    Description:
    
    Changes
    11/22/2017
    */
    AS
    BEGIN
         -------------
         -- Assemble
         -------------
         DECLARE @begin DATETIME = '1994-01-01' ,
                 @end DATETIME = '2000-01-01' ,
                 @month TINYINT = 1;
    
        EXEC tSQLt.FakeTable @TableName = 'birthdays', @SchemaName = 'dbo';
         INSERT dbo.birthdays
         (
             cust_id ,
             cust_fname ,
             cust_lname ,
             cust_dob
         )
         VALUES
         (94, N'Jamie', N'Aguiar', '2017-06-02 00:00:00.000') ,
         (346, N'Keith', N'Brady', '1993-03-29 00:00:00.000') ,
         (361, N'Kelsea', N'Britto', '1994-03-25 00:00:00.000') ,
         (715, N'Tia', N'Delguidice', '1999-02-04 00:00:00.000') ,
         (994, N'Holly', N'Hamilton', '2017-11-12 00:00:00.000') ,
         (1110, N'ISABELLE', N'HYDER', '1993-04-06 00:00:00.000') ,
         (1295, N'RAELYN', N'LITTLE', '1995-02-15 00:00:00.000') ,
         (1403, N'ALLISON', N'RIPA', '1993-10-14 00:00:00.000') ,
         (1486, N'Rayvon', N'Miller', '1984-11-09 00:00:00.000') ,
         (1559, N'Alexandra', N'Sousa', '1989-09-17 00:00:00.000') ,
         (1897, N'Patrick', N'Snow', '1976-10-10 00:00:00.000') ,
         (1749, N'Justine', N'Zienowicz', '1998-03-12 00:00:00.000'),
         (2209,N'Brittany',N'Kosboski','1987-01-22 00:00:00.000')
         ;
    
        CREATE TABLE #Expected
         (
             cust_id INTEGER NOT NULL PRIMARY KEY ,
             cust_fname NVARCHAR(50) NOT NULL ,
             cust_lname NVARCHAR(50) NOT NULL ,
             cust_dob DATETIME NOT NULL
         );
    
    
    
    
        SELECT TOP 0
             cust_id ,
             cust_fname ,
             cust_lname ,
             cust_dob
         INTO #Actual
         FROM #Expected;
    
        ---------------
         -- Act
         ---------------
         INSERT #Actual
         SELECT cust_id ,
                cust_fname ,
                cust_lname ,
                cust_dob
         FROM birthdays
         WHERE cust_dob >= @begin
               AND cust_dob < @end
               AND MONTH(cust_dob) = @month;
    
        ---------------
         -- Assert    
         ---------------
         EXEC tSQLt.AssertEqualsTable @Expected = N'#expected' ,
                                      @Actual = N'#actual' ,
                                      @Message = N'The query doesn''t work';
    
    END;
    
    
    GO
    -- GRANT EXECUTE ON tTSQLTests.[test birthday queries for a month] to userrole
    EXEC tsqlt.run 'tTSQLTests.[test birthday queries for a Jan with no birthdays in range]'

    Then I’d test for one birthday.

    CREATE OR ALTER PROCEDURE tTSQLTests.[test birthday queries for a Jan with one birthdays in range]
    /*
    Description:
    
    Changes
    11/22/2017
    */
    AS
    BEGIN
         -------------
         -- Assemble
         -------------
         DECLARE @begin DATETIME = '1984-01-01' ,
                 @end DATETIME = '2000-01-01' ,
                 @month TINYINT = 1;
    
        EXEC tSQLt.FakeTable @TableName = 'birthdays', @SchemaName = 'dbo';
         INSERT dbo.birthdays
         (
             cust_id ,
             cust_fname ,
             cust_lname ,
             cust_dob
         )
         VALUES
         (94, N'Jamie', N'Aguiar', '2017-06-02 00:00:00.000') ,
         (346, N'Keith', N'Brady', '1993-03-29 00:00:00.000') ,
         (361, N'Kelsea', N'Britto', '1994-03-25 00:00:00.000') ,
         (715, N'Tia', N'Delguidice', '1999-02-04 00:00:00.000') ,
         (994, N'Holly', N'Hamilton', '2017-11-12 00:00:00.000') ,
         (1110, N'ISABELLE', N'HYDER', '1993-04-06 00:00:00.000') ,
         (1295, N'RAELYN', N'LITTLE', '1995-02-15 00:00:00.000') ,
         (1403, N'ALLISON', N'RIPA', '1993-10-14 00:00:00.000') ,
         (1486, N'Rayvon', N'Miller', '1984-11-09 00:00:00.000') ,
         (1559, N'Alexandra', N'Sousa', '1989-09-17 00:00:00.000') ,
         (1897, N'Patrick', N'Snow', '1976-10-10 00:00:00.000') ,
         (1749, N'Justine', N'Zienowicz', '1998-03-12 00:00:00.000') ,
         (2209, N'Brittany', N'Kosboski', '1987-01-22 00:00:00.000');
    
        CREATE TABLE #Expected
         (
             cust_id INTEGER NOT NULL PRIMARY KEY ,
             cust_fname NVARCHAR(50) NOT NULL ,
             cust_lname NVARCHAR(50) NOT NULL ,
             cust_dob DATETIME NOT NULL
         );
    
        INSERT #Expected
         (
             cust_id ,
             cust_fname ,
             cust_lname ,
             cust_dob
         )
         VALUES
         (2209, N'Brittany', N'Kosboski', '1987-01-22 00:00:00.000');
    
        SELECT TOP 0
             cust_id ,
             cust_fname ,
             cust_lname ,
             cust_dob
         INTO #Actual
         FROM #Expected;
    
        ---------------
         -- Act
         ---------------
         INSERT #Actual
         SELECT cust_id ,
                cust_fname ,
                cust_lname ,
                cust_dob
         FROM birthdays
         WHERE cust_dob >= @begin
               AND cust_dob < @end
               AND MONTH(cust_dob) = @month;
    
        ---------------
         -- Assert    
         ---------------
         EXEC tSQLt.AssertEqualsTable @Expected = N'#expected' ,
                                      @Actual = N'#actual' ,
                                      @Message = N'The query doesn''t work';
    
    END;
    
    
    GO
    -- GRANT EXECUTE ON tTSQLTests.[test birthday queries for a month] to userrole
    EXEC tSQLt.Run 'tTSQLTests.[test birthday queries for a Jan with no birthdays in range]';
    EXEC tSQLt.Run 'tTSQLTests.[test birthday queries for a Jan with one birthdays in range]';

    Next, I’d add a few more tests for other cases, perhaps checking that leap years, etc. run correctly.

    Is this hard to setup? Well, I might argue that the time you spend examining result sets and checking random queries is about the same. Once I’ve written this test, which took about 10 minutes with a template, I can easily copy/paste the test, change the name and move data around. Ideally I’d stick this query in some procedure instead and run the test that way, which makes it easy for me to alter the query and re-run a ton of tests quickly.

    The time saved isn’t in the initial development, but in the checking when I touch this code again, or tune it. What if I decided to replace the MONTH() check with a computed column, as suggested by some responders? Then my tests should still pass with a new query.

    Testing builds better software. Not perfect, but better. And I can get better as developing over time by adding more tests.