Tag: T-SQL

  • Watch Your DataTypes in Aggregates–#SQLNewBlogger

    Another post for me that is simple and hopefully serves as an example for people trying to get blogging as #SQLNewBloggers.

    I’ve got a database of NBA statistics with data like this for players. I downloaded a CSV and loaded it into SQL Server.

    2017-03-22 10_32_00-SQLQuery1.sql - (local)_SQL2016.NBA (PLATO_Steve (102))_ - Microsoft SQL Server

    I decided to play with the data a bit and at one point wanted to see who scored the most points for a team and year. So I ran this query:

    SELECT
        year,
        team,
        MAX(pts)
    FROM dbo.player_regular_season
    WHERE
        year = ‘1972’
        AND team = ‘LAL’
    GROUP BY
        year,
        team;

    The result was 705. That’s a decent number of points, and if I weren’t careful, this might seem fine. 1972 was a long time ago, and they didn’t score as many points as they do today in games.

    In fact, if I were putting this in a summary report with lots of data, it might be the case that someone glancing at this would make a poor decision based on the data.

    Why?

    Let’s look at the data.

    2017-03-22 10_46_16-SQLQuery1.sql - (local)_SQL2016.NBA (PLATO_Steve (102))_ - Microsoft SQL Server

    Even a quick glance would let me know this seems funny. There are values of 1575 and 1084 in there, but the MAX() I returned was 705. If I look deeper at the import, I can see why.

    2017-03-22 10_47_25-SQLQuery1.sql - (local)_SQL2016.NBA (PLATO_Steve (102))_ - Microsoft SQL Server

    Anything stand out there? If you look, pts is a varchar, not a numerical value. In the character world, 705 beats 1575. I really need this query:

    2017-03-22 10_48_30-SQLQuery1.sql - (local)_SQL2016.NBA (PLATO_Steve (102))_ - Microsoft SQL Server

    Always be aware of the datatypes you work with and manipulate. Knowing a little bit about the meaning and use of the data can help you spot anomalies like this. As much as I like random test data, I’d also be sure you have some real data cases when you have users check your work. It’s easy for them to miss problems like this without good reference cases.

    Or use good test data that you’ve setup and unit tests.

  • Implicit Time Conversions – #SQLNewBlogger

    Another post for me that is simple and hopefully serves as an example for people trying to get blogging as #SQLNewBloggers.

    I was trying to work with times recently and needed to get the current time. I thought, well, Getdate(), or better yet, SysDateTime() will give me a date and time, but what about the time?

    A simple experiment showed it’s easy:

    DECLARE
        @t TIME,
        @t1 TIME;
    SELECT @t = SYSDATETIME(), @t1 = GETDATE();
    SELECT @t, @t1;

    I got this:

    2017-02-24 12_34_19-SQLQuery2.sql - (local)_SQL2016.PartsUnlimited_Grant (PLATO_Steve (59))_ - Micro

    Quick, easy, and what I suspected would work. If you need to work with times, you can easily cast a datetime value to a TIME to strip the date, or just assign the values to a time.

    CREATE TABLE TimeTest
    (t TIME)
    GO
    INSERT TimeTest
    SELECT top 10
     CreationDate
     FROM dbo.Posts
     GO
     SELECT top 10
      *
      FROM dbo.TimeTest
    GO
    DROP TABLE TimeTest

    This code takes a datetime column and just inserts the time into the new table.

    SQLNewBlogger

    Literally about 3 minutes of my day to write this. When you learn something, write it down.

  • Writing the Correct Query is Important

    There’s a saying in the data world: garbage in, garbage out. We use that when we can’t get good information from our database because the data we’ve stored isn’t as useful as we would like. That’s a problem, and it’s one reason why data professionals want to spend time thinking about the data we need to collect and how to store it. We want to be sure that we’ve at least made an effort to collect useful data that someone will use.

    We sometimes have the data we need, but still struggle to use it effectively. I think this is an area where machine learning and similar technologies may help in the future, but there is a lot of work to be done to allow most of us to take advantage of those tools. In the meantime, many of us make do with basic T-SQL to perform data analysis, generate reports, and provide the answers to questions. When we do so, it’s important that our queries actually work correctly to answer the questions we need.

    I don’t want this to be a political discussion, and I would appreciate that any comments be limited to the technical subject. I ran across a piece about a failure of the US government in determining the status of people being checked for immigration status. The interesting quote in this article was “… officials blamed computer code for the problem.” Leaving aside the implications in this case, the idea that computer code, likely some sort of query code, is not working as expected, querying the correct data, or isn’t being used properly is disturbing.

    I’ve run across quite a few stories like this from various consultants that were called in to help organizations, only to find out the queries that had been used for long periods of time were incorrect. They didn’t filter appropriately, didn’t convert or aggregate data as intended, or didn’t even query the correct data.

    We use databases and queries extensively in today’s world, and the growth is only going to increase. As much as I like the idea of DevOps and more frequent deployments, I also want higher quality for our software. This means that we need to ensure that our queries actually work as intended against databases. Code reviews, independent checks, using known data sets that evolve and include edge cases of data are all ways we can work to ensure we are actually writing the correct queries for our data. Above all, we need to be sure we are using test of some sort, preferably unit tests, that ensure the queries are actually the ones we want.

    Steve Jones

    The Voice of the DBA Podcast

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

  • Quick Prompt Tips–Custom Procedure Templates

    One of the things that I often do is create stored procedures. The syntax for doing so is simple, but it has a number of items that need to be included. SQL Prompt makes this much quicker with the “cp” snippet. When I type “cp”, I get this:

    2016-09-13 13_01_43-SQLQuery1.sql - (local)_SQL2016.AlwaysEncryptedDemo (PLATO_Steve (64))_ - Micros

    I can hit Tab and I have a snippet, but it has a lot of things I don’t like in it. Plus, I want to save time coding, not have to remove some commented out items.

    2016-09-13 13_06_17-SQLQuery1.sql - (local)_SQL2016.AlwaysEncryptedDemo (PLATO_Steve (64))_ - Micros

    Let’s make this more efficient. I can go to the Snippet Manager under the SQL Prompt menu and select it. When it opens, the snippets are highlighted, so I type “cp” to get to the Create Procedure snippet.

    2016-09-13 13_36_11-SQLQuery1.sql - (local)_SQL2016.EncryptionDemo (PLATO_Steve (64))_ - Microsoft S

    I click edit and see the code, which I highlight before deleting this.

    2016-09-13 13_36_45-SQL Prompt - Edit Snippet

    Then I paste in the code that makes more sense to me. Notice that in my case, I have two placeholders, not one (as shown above).

    2016-09-13 13_37_03-SQL Prompt - Edit Snippet

    The code I use has a header in the procedure, and the procedure name is used both for the definition and a GRANT EXECUTE. I include the begin..end structure for the procedure with the cursor starting in the spot where I’d put code. I also have a placeholder for a role name. It looks like this.

    CREATE PROCEDURE $procedure_name$

    /*
    Description:

    Changes:
    Date       Who Notes
    ———- — —————————————————
    */
    AS
    BEGIN
    $CURSOR$
    END
    GO

    GRANT EXECUTE ON $procedure_name$ TO $role_name$

    In practice, when I type “cp” and hit Tab, I get the code with the procedure highlighted. I can enter a name here. Note what I typed is also placed in the GRANT statement at the bottom.

    2016-09-13 13_40_02-SQLQuery1.sql - (local)_SQL2016.EncryptionDemo (PLATO_Steve (64))_ - Microsoft S

    Once I am done and hit Tab, my cursor jumps to the next placeholder, in this case, the role name. Notice that SQL Prompt knows this is a role and gives me a list of roles and users to choose from.

    2016-09-13 13_40_44-SQLQuery1.sql - (local)_SQL2016.EncryptionDemo (PLATO_Steve (64))_ - Microsoft S

    When I finish and hit Tab again, the cursor jumps to the point between the BEGIN and End where I will enter my code. Now my job begins.

    2016-09-13 13_42_26-SQLQuery1.sql - (local)_SQL2016.EncryptionDemo (PLATO_Steve (64))_ - Microsoft S

    This little customization gives all my procedures some standard look as well as ensuring that I can quickly build procedures without a lot of mundane, tedious typing.

    Try out this quick SQL Prompt tip and see how much smoother your coding goes. And if you’re not a SQL Prompt user, download an evaluation today and see how much more efficient you can be when writing T-SQL code.

    You can see a complete list of SQL Prompt tips at Redgate.