Author: way0utwest

  • The Office

    This editorial was originally published on Dec 29, 2010. It is being re-run as Steve is on vacation.

    An article caught my eye. The majority of workers think they can be productive outside of an office in a survey conducted of 2,600 IT professionals. Most of the these people also said that they tended to work extra hours each day outside of the office. The majority also said they would take a lower paying job if they could access the information they needed outside the office.

    That’s actually a smaller percentage that I expected would want to work away from an office,  though more than I expected would actually take less pay to do so. As least in America, it seems that people are very concerned with their salary, and reluctant to ever take a pay cut. I’m glad it seems that some people are starting to understand that value of their time to themselves and their families.

    It’s hard to work at the office, as Jason Fried said recently in a TED Talk. I haven’t worked in an office in some time, but I do remember a constant stream of interruptions. An hour of time without someone talking to you was rare, and I assume that the situation is similar with many knowledge workers today. We have people that we pay to think, and solve problems, but we don’t give them the time to actually work on those problems.

    Steve Jones

  • Puzzled by T-SQL

    Live blogging this a bit as I try things. This will update a bit, so you’ll have to read through.

    Adam Machanic posted this: T-SQL Puzzle-How many rows will this return? SELECT*FROM(VALUES(1),(2))AS x(i)WHERE EXISTS(SELECT MAX(i)FROM(VALUES(1))AS y(i)WHERE y.i=x.i)

    I was in a doctor’s office waiting at the time, but I responded that I didn’t think one row was right. I didn’t have the chance to see what happened, so I couldn’t reason through what was happening. Maybe I should have been able to? Not sure.

    I got home and ran this (thanks, SQL Prompt):

    SELECT
         *
       FROM     ( VALUES ( 1), ( 2) ) AS x ( i )
       WHERE     EXISTS ( SELECT  MAX(y.i)
                        FROM
                        ( VALUES ( 1) ) AS y ( i )
                   WHERE
                     y.i = x.i );
    

    I get two rows back, a 1 and a 2. Very strange.

    I tried experimenting a bit. I created tables and put data in there. Maybe there’s something I don’t get in the VALUES() clause.

    CREATE TABLE mytable99 (id INT);
    CREATE TABLE mytable999 (id INT);
    GO
    INSERT dbo.mytable99
    ( id )
    VALUES
    ( 1 ), (2);
    INSERT dbo.mytable999
    ( id )
    VALUES
    ( 1 )
    ;
    GO
    SELECT
    *
    FROM
    dbo.mytable99 AS x
    WHERE
    EXISTS ( SELECT MAX(y.id)
            FROM dbo.mytable999 AS y
            WHERE y.id = x.id );
    
    

    Same result.

    Hmmm, Adam added a clue. Why does select max(1) work?

    2015-12-03 13_43_15-Photos

    I was guessing that max() operates on the scalar set of [1]. However I’m not sure.

    I then did this:

    UPDATE dbo.mytable999 SET id = 9;
    

    When I re-ran the query, still two rows. Without a match.

    Next I added another row to the first table.

    INSERT dbo.mytable99
    ( id)
    VALUES
    ( 3 );
    

    Now I get three rows.

    What I’m guessing (at this point) is that the correlated subquery returns a 1 for every row of the first table, so this means I get the size and shape of that table. The EXISTS() is always satisfied.

    I’ll be interested to learn what is happening, or if I’m right.

    Update: I’m not.

    Or semi-right.

    The exists is satisfied, but why?

    Adam posted a second hint asking me to remove the max(). I did that and got 1 row. Well that’s interesting. How does the aggregate affect the correlated subquery, and how does this affect the Exists().

    I decided to break down the query inside the EXISTS(). I did this with scalar values. Since I’ve been dealing with two rows, I used those two scalar values.

    	 SELECT
                    y.i --MAX(y.i)
                  FROM
                    ( VALUES ( 1) ) AS y ( i ) 
    			  WHERE
                    y.i = 1 ;
    
    	 SELECT
                    y.i --MAX(y.i)
                  FROM
                    ( VALUES ( 1) ) AS y ( i ) 
    			  WHERE
                    y.i = 2;
    

    With these queries, I get one row and zero rows, just an empty set. That makes sense in terms of why removing the MAX() gives me one row in the whole thing.

    Next I added the MAX back.

    	 SELECT
                    MAX(y.i)
                  FROM
                    ( VALUES ( 1) ) AS y ( i ) 
    			  WHERE
                    y.i = 1 ;
    
    	 SELECT
                    MAX(y.i)
                  FROM
                    ( VALUES ( 1) ) AS y ( i ) 
    			  WHERE
                    y.i = 2;
    

    Now I get one row for the first, and one row for the second? Huh? However the second set is a row with NULL in it. I checked the EXISTS() documentation, and sure enough, if there are rows, this returns true, even if the row has a null value. This isn’t the value of a row, but rather just its presence.

    I then did this to check:

    SELECT 'test' = 1
     WHERE EXISTS( SELECT * FROM mytable WHERE 1 = 0);
    
    SELECT 'test' = 1
     WHERE EXISTS( SELECT null);
    

    Sure enough, the first gives me an empty result set, while the second doesn’t.

    But why does MAX() return a row? I tried this with a simple query:

     SELECT MAX(i)
      FROM ( VALUES (1)) AS x(i)
      WHERE x.i = 2

    Which does return NULL. I did search and saw this explanation on SO, saying that the result of the MAX() for the group (where x.i=2) is undefined, hence the NULL. This is born out as you see here:

    CREATE TABLE mytable88(i INT);
    GO
    SELECT MAX(i) FROM dbo.mytable88 AS m;
    

    Strange. Certainly I wouldn’t have expected that from MAX(). I would have thought it was an empty set, but apparently that’s not the case.

  • What is DevOps?

    There is a lot of confusion in the world about DevOps. Some of that might be because the concept hasn’t been well defined, or implemented, in many organizations. It might also be because other companies have been running as DevOps organizations for years without having a name for what they did and no good way to talk about their practices as a whole. Plenty of those efficient organizations resent having DevOps presented as a “new” idea when it’s been their modus operandi for years.

    I an across a primer on DevOps that I thought was a good explanation for management. It’s not perfect, and the piece minimizes the problems of changing culture and attitude. There is an emphasis on breaking down barriers and silos, but no discussion as to how managers should do this. I think most people expect managers to know how to get teams to work together, but in practice, I have found few managers that could do this.

    There is no magic to DevOps. There isn’t a tool you can buy, or a consultant that you can hire to implement it. All you can do is get help and guidance in helping your staff to learn to work more closely together. Developers have to learn to consider the operational impacts of their work, while formalizing some of their processes. They need to automate their testing, but also the packaging and installation of their software, while working in standardized environments. Operations is the flip side of this, in that Operations staff must be responsive and quick to build the standard environments developers need. They must work with developers to feedback issues and requirements from Operations to the developers, including bugs that can be caught with changes to the automated testing processes.

    DevOps is about working together. With respect and professionalism, but also the attitude that we can help each other do our jobs better. This impacts our compensation and reward systems, as well as organizational structures. I wouldn’t underestimate the impact this has on the way an IT department works, but I also wouldn’t be afraid of the changes. However I would move slowly, evaluating the impacts as processes change, and working to assuage the fears and concerns of your staff.

    Ultimately DevOps, in my mind, isn’t about saving money or getting software build faster. It’s about working together to become more responsive to our clients as our software becomes ever more important to them.

    Steve Jones

    The Voice of the DBA Podcast

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

  • Ending My Loop in PowerShell Early

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

    I was modifying my PowerShell (PoSh) script to download SQL Saturday files recently to not re-download files. However when I did this, I also realized that I didn’t necessarily want the script to run too long.

    One of the challenges of downloading the data is that I don’t know how many events exist. We don’t keep that number handy, and it changes regularly. One of the things I decided to do was run my process in a loop.

    While ($i -lt 9999) {

    That’s fine, but it’s not a great loop. It runs 9999 times, which isn’t what I want. It works, but it’s an unnecessary use of resources. However I don’t want to break the loop when the file file isn’t found. There have been issues generating a file, like #350, when #351 exists and is there.

    I decided to use a shortcut technique I had learned as a kid. I set a variable and then incremented it when I missed a file. When the increment reaches some value, I break the loop.

    I decided to use 12 as my number of missed. No good reason, but that’s what I picked. I started by putting a variable outside of the loop.

    $missedXML = 0
    While ($i -lt 9999) {

    Then I increment this variable in the CATCH section of my error handler.

    Catch 
    { 
      # if we can't load the file, assume we're done for now. 
      $missedXML++ 
      Write-Host "error with  #" $i 
    }

    Finally, I set up an IF loop at the bottom of the loop. If I’ve missed 12 times, I break the loop by setting the counter to the last value.

    $i = $i + 1
    if ($missedXML -ge 12) { 
     $i = 9999 
    }

    I tested this with some debugging information and what I found was that when I got to 494, I started missing files. As soon as I hit 12, the loop ended.

    Enhancement complete.

    SQLNewBlogger

    This post came about when I started working on the script. I made the modifications from the previous post and decided to also fix the extra loops with this technique.

    This post took about 10 minutes to write.

    References

    No resources needed here. I’ve got enough PoSh knowledge to handle this task myself.