Author: way0utwest

  • Advent of Code–Day 2

    I’ve continued working along, and while I found Day 2 to be straightforward in Python and PowerShell, I thought it was tricky in SQL I decided this one was worth a post, since I had to futz around a few times to solve it, and I managed a slightly different way than some others.

    If you haven’t solved it, then try. Come back here later and compare solutions, but give it a try first.

     

    Solution coming below, so don’t scroll if you don’t need the solution.

     

     

     

     

     

    But first,

     

     

     

     

     

    Missteps

    I had a misstep in this one. I loaded the entire list of packages as separate lines into separate rows into a single column table. My challenge to myself was not to use ETL work to break this apart, or updates. I wanted a simple solution, thinking I didn’t want to take up extra space in the database.

    As a result, I wanted a single query from a single string column that had the package size stored as one column, ‘2x3x4’ as an example.

    My first attempt used the Moden Splitter function, which seemed to work well. I got three rows for each package. I then used a WIndow function to grab that data, order by the sizes, and then start performing calculations. When I didn’t get the right result, I started digging in.

    One of the first things I saw was that I had multple packages with the same sizes. So I had two 22x3x1 packages, and when I used a partition based on the dimensions, I had calculation problems. That’s because the window partition doesn’t know that three rows are one package and three are another.

    I could have fixed this with some other value to capture the package, maybe a row_number even, but I decided not to go down this route.

     

     

     

     

    My Solution

    I decided to break this down, and I used a series of CTEs to do this. I haven’t gone back to optimize things, or combine CTEs, which is possible, but instead left the CTEs as I wrote them to solve parts of the puzzle. Multiple CTEs are east, and they help examine the problem in pieces.

    My first step was to parse the string. I don’t love this solution as it is limited to a three dimension package, but it does seem to be the easiest way to break down the dimensions of the package. My query looks to find the string positions for:

    • end of the first dimension
    • start of the second dimension
    • start of the third dimension.

    This gives me the simple query:

    with cteSplit (d, el, sw, sh)
    as
    (
    select
       dimensions
    , endlength = charindex(‘x’, dimensions) – 1
    , startwidth = charindex(‘x’, substring(dimensions, charindex(‘x’, dimensions),20)) + charindex(‘x’, dimensions)
    , startheight = len(dimensions) – charindex(‘x’, reverse(dimensions))  + 2
    from day2_wrappingpresents d
    )

    Once I had these values, a little math gives me the length, width, and height.

    , cteDimensions
    as
    (select
       d
       , l = cast(substring(d, 1, el) as int)
       , w = cast(substring(d, sw, sh-sw-1) as int)
       , h = cast(substring(d, sh, len(d)) as int)
    from cteSplit d
    )

    Now I’m in business. These two queries were fairly simple, despite all the nested functions. I’ve got integers with the dimensions of each package.

    Now the tricky part. I want these ordered. They’re columns, not rows, and I can’t put an ORDER BY in the CTE, so I need to use some comparisons.

    , cteOrder
    as
    ( select
       d
    , small = case
                when l <= w and l <= h then l
                when w <= l and w <= h then w
                when h <= l and h <= w then h
            end
    , middle = case
                when (l >= w and l <= h) or (l <= w and l >= h) then l
                when (w >= l and w <= h) or (w <= l and w >= h) then w
                when (h >= l and h <= w) or (h <= l and h >= w) then h
            end
    , large = case
                when l >= w and l >= h then l
                when w >= l and w >= h then w
                when h >= l and h >= w then h
            end
      from cteDimensions
    )

    Not the prettiest code, and perhaps there are better ways to determine this, but this passed all my tests, and seemed to work.

    I could have put the next part in the final query, but I decided to make this a separate CTE to easily read the math. I know some people don’t like lots of CTEs, but in this case, I think they make the query very readable. I should look back at this in six months and see what I think.

    , cteFinal
    as
    (
    select
      d
      , area = (2 * small * middle) +
               (2 * small * large) +
               (2 * middle * large)
      , slack = (small * middle)
    from cteOrder
    )

    Now I use a final outer query to sum things up.

    select
    sum(area + slack)
    from cteFinal

    The other thing I noticed here is that when I needed to solve the second part, I only had to change the math in the cteFinal to get the new values. It took longer to re-read the second part than to change the code and solve it.

    I looked over how Wayne Sheffield and Andy Warren solved this in T-SQL, and I thought their approaches were interesting. I didn’t want to PIVOT or UNPIVOT anywhere, nor did I look at performance here. This runs so quickly, I’m not sure it matters, though I wonder if we were calculating across 1mm rows, would one be better?

    I may look, but for now, I’ll leave that to someone else.

  • Disabling SQL Server Network Protocols

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

    I ran across a question on network protocols recently, which is something I rarely deal with. Often the default setup for SQL Server is fine, but there are certainly times you should add or remove network connectivity according to your environment.

    Here’s a short post on turning off (or on) a network protocol for SQL Sever.

    What’s Enabled?

    The easiest way to verify what’s enabled is to use the SQL Server Configuration Manager. You’ll need administrative permissions on the host to run this, but it’s easy to find.

    2016-01-13 14_59_40-Start

    Once you open it, typically you’ll have a list of the items that can be configured.

    2016-01-13 15_02_09-Photos

    We want the SQL Server Network Configuration, which is the server level configuration for this host. The Client configurations are for the host being used a client to connect to a SQL Server.

    2016-01-13 15_02_31-Photos

    As you can see here, I have Shared Memory and TCP/IP enabled for this instance, but Named Pipes disabled.

    Disabling a Protocol

    As you might expect, this is easy. I right click on a protocol, and I can change the status. In this case, I’ll disable Shared Memory

    2016-01-13 15_03_50-Photos

    Once I do that, the protocol is disabled. However not on the instance. I’ll get this message.

    2016-01-13 15_04_56-Photos

    I need to restart the server. Once that’s done, no one will be able to use Shared Memory on the host.

    I can fix this

    2016-01-13 15_04_49-Photos

    Of course, I need to restart my instance again.

    Checking the Log

    When SQL Server starts, quite a bit of configuration information is written into the log. This is useful for troubleshooting in many cases. One of the things you’ll find is the network listeners, as shown here.

    2016-01-13 15_08_14-Log File Viewer - JollyGreenGiant_SQL2016

    This is usually after the database startup information, so if you look, you can see I have some local pipes and some TCP/IP settings here.

    SQLNewBlogger

    After reading a question, this was less than 10 minutes to write, with making screenshots. However I’ve done this before. If this was your first time, then it might take you longer to research and write, but I bet most DBAs could do this in 30-45 minutes.

  • Chips and Margaritas at SQL Saturday #461

    It was a few years back that my wife and I planned a trip to the Austin City Lights music festival to see Stevie Wonder. This was a bucket list item for us, and we thoroughly enjoyed a long weekend in the city. I’ve been for SQL in the City as well, and each time I’ve gone, I’ve enjoyed a lunch at one of the Mexican restaurants South of the river. My kids always joke that my wife and I will fill up on chips and margaritas at Mexican restaurants, and it’s somewhat true. Often dinner becomes lunch the next day.

    It’s just two weeks to SQL Saturday #461 in Austin, and I’m looking forward to going back. In fact, I’m going to make it a point to at least go get chips and a drink at the same place. I can’t remember the name, but I know how to get there, so I’ll be fine.

    However the main event is the free, one day SQL Saturday event taking place. I’ll be there delivering my Branding for a Dream Job presentation, but there are tons of other great talks. From AlwaysOn to Power BI to Azure to Writing Faster Queries, you’ll have a great day of learning on all sorts of SQL Server topics.

    If you’re anywhere near Austin, register today and come join us in Austin for a fun day that kicks of my SQL Saturday 2016 tour.

  • Security Convenience

    I wrote a question of the day recently that seemed to catch many people. The question had to do with mapping users when a login isn’t specified in the call. The behavior is to auto match existing logins with the same name. About 60% of the people answering the next day got it right, but a third missed it, expecting an error to be thrown.

    One of the commenters was surprised that more people didn’t know this. I’d hope people knew this, though to be fair, I bet lots of people manage security through SSMS or a GUI and never write security code. I know I did for years early on. However I really think that the third of the people that got this wrong in its behavior, are actually right about how SQL Server security should work.

    We do not want ambiguity when we configure security. We should be sure that rights granted (or removed) are exactly those that we expect. A strong security system should not tolerate any unexpected behaviors.

    Security should require specificity.

    Steve Jones

    The Voice of the DBA Podcast

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