Tag: T-SQL

  • The Basics of Joins – Skill #4

    This series of blog posts are related to my presentation, The Top Ten Skills You Need, which is scheduled for a few deliveries in 2011.

    Databases are built to store data. That’s the primary purpose, and in SQL Server, we store data in a relational form. That means that often we have data spread across multiple tables. Why we do this is a discussion for another day, but suffice it to say that we often have structures like this:

    personcontact

    Part of the person.contact table in AdventureWorks above and the HumanResource.Employee table below.

    employee

    One typical join task might be to get an employee’s name, or a list of employees and their names. Here we have a birthday in the Employee table, but we don’t have a name. That’s in the Person.Contact table. Essentially we want to match these up using basic, elementary school set theory.

    settheory

    In the diagram above, you can think of each letter as a row in a table. As an example, let’s assume that B in the orange circle represents the row in the employee table with a ContactID value of 4. The B in the pink circle would represent the row in the Contact table with a ContactID value of 4 as well.

    When we join these to get the Employee name and birth date, we get:

    join2

    I used a join in my query to get that:

    SELECT 
      c.firstname
    , c.LastName
    , e.BirthDate
     FROM person.contact c
       INNER JOIN HumanResources.Employee e
         ON c.ContactID = e.ContactID
     WHERE c.ContactID = 4
     

    In this query I’ve included two tables in the FROM clause with the INNER JOIN key phrase between them, which specifies I only choose the matching rows. The match is made in the ON clause.

    I’ve also qualified this to only apply to the row with a ContactID of 4 in the WHERE clause.

    There’s a lot more you can do with joins, and you can include more than two tables, such as this query:

    SELECT 
      c.firstname
    , c.LastName
    , e.BirthDate
    , pa.AddressLine1
    , pa.AddressLine2
     FROM person.contact c
       INNER JOIN HumanResources.Employee e
         ON c.ContactID = e.ContactID
       INNER JOIN HumanResources.EmployeeAddress ea
         ON e.EmployeeID = ea.EmployeeID
       INNER JOIN person.Address pa
         ON ea.AddressID = pa.AddressID
     WHERE c.ContactID = 4
     

    I would recommend that you practice working with basic joins, based on the information that you commonly see queried in your application. Sooner or later someone will ask you for some data that isn’t available in the application and you will want to write a query to extract it for them.

  • Basic Inner Joins – Basic Skill #4

    This post is part of a series based on my presentation The Top Ten Skills You Need for SQL Server. This post is part of Skill #4 – Joins.

    T-SQL Tuesday #23

    This post is also serving as my T-SQL Tuesday post for the month. This month the party is brought to you by Stuart Ainsworth. If you want to know more about what T-SQL Tuesday is about, read Stuart’s post as well as Adam Machanic’s original post and then join in next month.

    An inner join is essentially an intersection of two sets. If you go back to grade school, and think about sets, you can have two items like this:

    set1

    If you look at these two sets, you see that there are various elements in each set. If we were to show the intersection, it would be this set: (B). This is shown below (excuse my horrible artwork):

    set2

    In SQL, we deal with tables, but we can model this as follows:

    CREATE TABLE SET1
    ( mychar varchar(1) ) GO CREATE TABLE SET2
    ( mychar varchar(1) ) GO INSERT SET1 SELECT 'A' INSERT SET1 SELECT 'B' GO INSERT SET2 VALUES ('B'), ('C'), ('D') GO SELECT a.mychar
      , b.mychar
     FROM SET1 a
       INNER JOIN set2 b
         ON a.mychar = b.mychar
    mychar mychar
    ------ ------
    B      B

    The results are the matching values in each table. In this case each table is a single column, modeling the images above where there is a single letter in each item of the set. The matching columns are the join columns, and in database work, these would be the data items that we are storing in both tables.

    However to expand this, in a database table, we usually have multiple items, so each letter could be a series of data elements, or could have a series of other fields attached to it. Suppose I change these “sets” a little:

    DROP TABLE set1
    DROP TABLE dbo.SET2
    go CREATE TABLE SET1
    ( mychar varchar(1) , Customer VARCHAR(50) , ActiveDate datetime ) GO CREATE TABLE SET2
    ( mychar varchar(1) , Customer VARCHAR(50) , ActiveDate datetime ) GO INSERT SET1 SELECT 'A', 'Bob', '1/1/2011' INSERT SET1 SELECT 'B', 'Bill', '2/1/2011' GO INSERT SET2 VALUES ('B', 'Steve', '1/2/2011'), ('C', 'Andy', '3/1/2011'), ('D', 'Brian', '3/3/2011') GO SELECT a.mychar
      , b.mychar
     FROM SET1 a
       INNER JOIN set2 b
         ON a.mychar = b.mychar

    I still only have one matching row, but there are other data points. If I alter my diagram, they look like this:

    set3

    The matching rows, in this case the rows with a “B” in them, have different data, which seems to be an issue. However suppose set 1 was a list of customers along with their first order date and set 2 was a list of salespeople and the dates they started. Then the join might be on sales, with the letter (A, B, C, D) representing the order.

    That’s the basic of a join. It gets complicated as you look to join three, four, or more tables, but this is the basic idea of an inner join in SQL.

  • Decimal Data Types in SQL Server

    I learned something new about decimal data types in SQL Server recently. If you do something like this:

    DECLARE @d DECIMAL(10,10)
    SET @d = 1.0

     

    You get this:

    Msg 8115, Level 16, State 8, Line 2

    Arithmetic overflow error converting numeric to data type numeric.

    That threw me for a minute since I’d never experienced it, but then I realized what was going on. The declaration of a decimal data type goes like this:

    DECLARE @d DECIMAL( @p, @s)

    Where we have

    • d – the name of the variable
    • p = precision, the number of digits in the number.
    • s = scale, the number of digits for the decimal

    You can think of this as the following,

    @d = nnnn.ssss

    Where the count of n’s and s’s must equal p.

    In the first example above, I’ve essentially declared:

    @d = 0.ssssssssss

    There’s no room for a digit, other than zero, to the left of the decimal. So you get an error. If I’d added one more digit to the p variable, like this:

     
    DECLARE @d DECIMAL(11,10)
    SET @d = 1.0

    I don’t receive an error. Likewise, I can add multiple digits to the other side like this:

    DECLARE @d DECIMAL(10,10)
    SET @d = 0.999999999

    Works fine.

    I had never run into this because I don’t ever declare these the same. I almost always go larger than I need, and allow for more decimals. So for US money, I often declare things at decimal(10,3), giving me more space than needed. It pays to think ahead, and declare your variables properly, and understanding how they are structured is part of that.

    Note: this applies to numeric types as well.

  • Data Presentation – T-SQL Tuesday #22

    TSQL2sDay150x150It’s T-SQL Tuesday again, with our host this month being Robert Pearl, of Pearl Knowledge Solutions. He chose the topic of Data Presentation for September.

    If you haven’t participated in a T-SQL Tuesday, it’s easy. Read the rules in Robert’s post and read the basic idea in Adam Machanic’s original invittation. Then write a blog post with the logo to the right in it and link it back to Robert’s post.

    That’s it.

    Formatting Data

    One of the things that DBAs and data professionals should learn is that formatting typically doesn’t belong in the database. The client, front end, or the tools used to extract the data should handle formatting, presenting the data as the client wants to see it.

    When you store numbers, you don’t want to store things like currency symbols. So in SQL Server I should see this:

    datapresent1

    and not this:

    datapresent2

    The former gives more flexibility, and the latter limits what you display (and requires character storage).

    The same thing goes for other data, for example, phone numbers. We don’t want to store our phone numbers like this:

    datapresent3

    If someone wants to see just the number, or they add in another format of number (say European), then you have inconsistencies. Also, it becomes harder to separate out issues. When you do separate out the number from the area code, how do you handle things if you have this:

    datapresent4

    That’s hard to handle. If all the phone numbers were numbers, it’s easier to handle. This allows one easy CASE statement based on length.

    datapresent5

    Or better yet, use better design and let the front end handle data presentation.

    datapresent6

    Doing It Right

    I guess I haven’t talked data presentation so much as how not to handle data presentation. I know that SQL Server can do things like ordering, formatting, combining or splitting strings, or more, but ultimately I think that’s not the right way to handle things.

    I’ve always viewed the database as the single bottleneck. It’s incredibly hard, and expensive, to scale a database server, while it’s easier to scale web servers, app servers, and client tools, and much less expensive. It’s even easier to scale developers and have them write more code to handle presentation on the front end instead of using SQL Server to do the work. I’d try to always push any presentation work to the client instead of the database server, just because of the workload and bottleneck on the server.

    It might seem like more work up front, and it will be, but it will be infinitely better than trying to re-write code or upgrade your database server later when the load becomes larger.