Category: Blog

  • Getting Row Numbers with Window Functions–#SQLNewBlogger

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

    In a recent post, I started looking at some basics for window functions. This post continues with a look at one of the most commonly used ones: row_number().

    Rows in a table aren’t in any particular order. They can be physically stored in order by the clustered index, but in a SELECT, there is no guarantee of any particular order unless you have an ORDER BY clause. However, even when you get a set or rows, there isn’t any number for the rows that is given.

    Many of us would like to have some number that allows us to know this is row 1, row 2, etc.

    We can do that with ROW_NUMBER(), which is a window function that assigns sequential numbers to rows. In the previous post, I used some baseball data, so I’ll continue with that today, but I’ll use another amazing batter, Ken Griffey Jr.

    If I just get the list of batting records for Ken, I see this results (abbreviated) below. Note that there is no ordering I can count on here. The row number to the right is added by SSMS, but isn’t in the result set:

    2021-07-13 11_34_04-SQLQuery1.sql - ARISTOTLE.BaseballData (ARISTOTLE_Steve (75))_ - Microsoft SQL S

    If I want to ensure every client has a row number, I can use that function with an OVER() clause. Note that I need to include something in the OVER() clause.

    2021-07-13 11_35_33-SQLQuery1.sql - ARISTOTLE.BaseballData (ARISTOTLE_Steve (75))_ - Microsoft SQL S

    Let’s fix that. I’ll order by year and then ensure I show the SSMS number added by the GUI. I see the numbers seem to correspond to the years. What if I order the entire query by team?

    2021-07-13 11_38_32-SQLQuery1.sql - ARISTOTLE.BaseballData (ARISTOTLE_Steve (75))_ - Microsoft SQL S

    This appear to have reversed the numbers. However, note that rows 11 and 12 are the 22 and 23. The window function applied the numbers based on the ordering of years for the entire set, then the rows were re-ordered for the query based on the ORDER BY. We see this more clearly with an ORDER BY using the HR column.

    2021-07-13 11_41_59-SQLQuery1.sql - ARISTOTLE.BaseballData (ARISTOTLE_Steve (75))_ - Microsoft SQL S

    What about just an ordering for the results? I do need an ORDER BY I can use this trick.

    SELECT   TOP 100
              ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Rowsetnumber
              , teamid
              , yearID
              , HR
    FROM     batting
    WHERE    playerID = 'griffke02'
    ORDER BY hr

    This allows me to just apply the ROW_NUMBER to whatever the query is doing. Here’s the result, ordered by HR.

    2021-07-13 11_45_14-SQLQuery1.sql - ARISTOTLE.BaseballData (ARISTOTLE_Steve (75))_ - Microsoft SQL S

    If I go back to my ordering by team, I see this:

    2021-07-13 11_46_48-SQLQuery1.sql - ARISTOTLE.BaseballData (ARISTOTLE_Steve (75))_ - Microsoft SQL S

    I can also add a PARTITION BY, and get numbering inside the partition or group. Here I’ll partition by team. I’ll go back to ordering by year, since that makes sense. I’ll use this query.

    SELECT   TOP 100
              ROW_NUMBER() OVER(PARTITION BY teamID ORDER BY (SELECT NULL)) AS Rowsetnumber
              , teamid
              , yearID
              , HR
    FROM     batting
    WHERE    playerID = 'griffke02'
    ORDER BY yearID

    The results are then shown with the numbering restarting with each team.

    2021-07-13 11_49_01-SQLQuery1.sql - ARISTOTLE.BaseballData (ARISTOTLE_Steve (75))_ - Microsoft SQL S

    The one strange thing to note here is that since Ken went back to Seattle late in his career, the numbering for his final two years show a continuation of the numbers from earlier with SEA.

    2021-07-13 11_49_12-SQLQuery1.sql - ARISTOTLE.BaseballData (ARISTOTLE_Steve (75))_ - Microsoft SQL S

    The ROW_NUMBER() function is very powerful and useful when you need some ranking and ordering to show to the client for the rows. As with all data, you need to ensure you understand the data set and be aware of how your partition (grouping) and ordering in the OVER() clause apply to the data, but the final results are dependent on the query’s ORDER BY. This can cause some confusion, so be sure you understand the difference and inform your clients.

    SQLNewBlogger

    This was a quick 10 minute post. I’ve done a lot of work with Window functions and presented on them, so this was a portion of a presentation I’d given, where I took part if a demo and wrote it up.

    However, you can experiment in 15-20 minutes and then spend 10-15 minutes structuring a post on this topic. How have you used ROW_NUMBER(), or if you’ve just learned it, what does it mean to you. Come up with some examples, ensure you understand them, and then explain them back. Might be an easy interview question to answer at some point if they find it on your blog.

  • Daily Coping 14 Jul 2021

    I started to add a daily coping tip to the SQLServerCentral newsletter and to the Community Circle, which is helping me deal with the issues in the world. I’m adding my responses for each day here. All my coping tips are under this tag. 

    Today’s tip is to get outside and move to help clear your head.

    I was a bit overwhelmed recently. Yesterday’s tip gives a few reasons, but there were others, and I had to lay down and try to relax one night, begging off from some plans and asking my wife to cancel things.

    I had things to do the next day, and started to make a list, but my wife suggested we skip some of these chores and go for a hike. It was one of the few times all kids were here, and nothing was so important that we couldn’t delay it, so we ended up taking a few hours, heading to a nearby park, and enjoying life for a bit outside. It was nice to think, walk, chat with family, and enjoy the day.

    Need to go out walking more.

    Plus, nice views.

    20210705_125303

  • Daily Coping 13 Jul 2021

    I started to add a daily coping tip to the SQLServerCentral newsletter and to the Community Circle, which is helping me deal with the issues in the world. I’m adding my responses for each day here. All my coping tips are under this tag. 

    Today’s tip is to write down some worries and save them for a specific worry time.

    I’ve been under a bunch of stress from managing lots of little things, both in life and at work. There are a few nagging things, but I’m going to drop them here and let them go for now. I’ll pick them up another day with my wife or my boss.

    • Deciding on how to finish a home renovation project (we have a small part to do)
    • Finding time to rebuild a garage shelf area to make room for something
    • Dealing with an outside contractor that isn’t as responsive for a work thing
    • A cash crunch coming up in a month or so and how to move the budget around
    • My ankle, which doesn’t like to hike more than about an hour
    • Getting a kid ready to drive cross country

    There are more, but I’m letting these go as they aren’t important this week, and we can deal with them in a week, or maybe this weekend, but not today.

  • Creating a Distribution List in SQL Multi Script

    SQL Multi Script is a lesser known tool from Redgate Software that is designed to easily allow you to run scripts against many server instances with one click of a button. It’s similar to a Central Management Server, but it returns results a little cleaner, and has a few extra features that make things run better. I have a number of customers using this to deploy to many instances, both for database changes and instance config updates.

    The main way to get setup is with a distribution list. This is a list of the instances and database you want to connect to. This post will show how to make one.

    The Default List

    By default, you have one list, and you can add instances to this. As you can see below, I’ve added a few instance and databases to my list, which is shown on the right side of the main application window.

    2021-07-12 08_31_03-SQL Multi Script - New Project_

    If I click the “Configure” button, I get a dialog that lets me manage these lists. It is shown below, with a mover in the middle to add or remove databases to the current list. In the upper right is a “New” button to add a list.

    2021-07-12 08_32_15-Configure Database Distribution Lists

    Let’s click that. This gives me a simple dialog to add a name. I’ll choose “InstanceMasters” for all the master databases on instances. This is a handy list when I want to add a login to all instances or make a config change.

    2021-07-12 08_33_35-Create New Database Distribution List

    Once I click “Create” I get back to the mover. This is where I select databases.

    2021-07-12 08_36_32-Configure Database Distribution Lists

    I can expand the instance on the left, and see all the databases. One note, the system databases are listed last, so scroll down. I’ll click “Add” in the middle to add this one.

    2021-07-12 08_36_49-Configure Database Distribution Lists

    I have a second instance on my machine, so let’s pick that. I’ll click the “Add a SQL Server Not Listed” at the bottom.

    2021-07-12 08_36_59-Configure Database Distribution Lists

    I get a connection dialog to specify the name and credentials.

    2021-07-12 08_37_29-Add a SQL Server Not Listed

    Once I complete this, I go back to the mover and I see my second instance. I’ll add that master database as well.

    2021-07-12 08_40_00-Configure Database Distribution Lists

    If I click OK, I now have my distribution list selected and set up. Any scripts I execute will go against these two master databases. If I needed to exclude one of the databases for a script, I could uncheck it, and in the image above, I can change distribution lists with the drop down below the Delete button.

    That’s a quick look at lists in SQL Multi Script. The tool lets me run multiple scripts against various databases, execute an ad hoc script, and get all the results with the instance/database name as well.

    It’s a very handy tool that not enough people use, so if you have the Toolbelt, give it a try. If down, download a SQL Multi Script evaluation today and see how this can help you in your daily work.