SQL SERVER – Tips from the SQL Joes 2 Pros Development Series – Advanced Aggregates with the Over Clause – Day 11 of 35

Answer simple quiz at the end of the blog post and –
Every day one winner from India will get Joes 2 Pros Volume 2.
Every day one winner from United States will get Joes 2 Pros Volume 2.

Partitioning with the Over Clause (Part 2)

Yesterday we learned how the over clause can be used to compare your number against the overall aggregated number for an entire result set. Sometimes you might want your number to be compared against its category and not all records from a table. For example I don’t get any joy in saying I never won the state championship in Greco Roman wrestling. On the other hand with great joy I tell people was the Tacoma City Champion. By partitioning the sport down into City instead of the entire country or state my ranking is much better.

Businesses might have other reasons for partitioning a group. Let’s use an example of schools where they see most of them getting a drop in attendance during the summer time. Comparing an attendance trend from spring to summer would not show an uptrend even if your school is growing year after year. It makes more sense to compare this summer to last summer to find a trend then to compare the spring and summer where you always see a drop. Whatever your reason you can get a total by a level of your choosing with the OVER() clause. Now let’s try an example using the aggregate function COUNT( ) with the OVER( ) clause. We’ll start with a simple query on the Employee table. Here we see Alex Adams is just 1 employee out of 13.  In fact each employee is one of 13 in this example.

SQL SERVER - Tips from the SQL Joes 2 Pros Development Series - Advanced Aggregates with the Over Clause - Day 11 of 35 j2p_11_1

Now let’s look at Alex Adams. He works in Location 1. How many of JProCo’s employees are in Location 1 (Seattle)? And how many of the total employees work in Boston? Alongside the existing table records, we want to add a column showing the count of employees at each location. Recall that blank parentheses cause OVER( ) to apply the aggregation across all rows of a query. Our instruction to show employee count at each location means we don’t just want a total of all locations in our query – we already have that data displayed in the TotalEmployees column. We must include an argument inside the parentheses. PARTITION BY divides the result set into partitions. In this case we’ve added a partition by LocationID.

SQL SERVER - Tips from the SQL Joes 2 Pros Development Series - Advanced Aggregates with the Over Clause - Day 11 of 35 j2p_11_2

Similar to the behavior of GROUP BY, the command to PARTITION BY LocationID takes the LocationID for each employee and counts the number of records in that group which shares the same LocationID. Thus, each of the Seattle employees shows a 7 for LocationCount. The Boston employees have a LocationCount of 3, and the Spokane records have LocationCount of 2. John Marshbank shows LocationCount of 1, since he’s the only one with a null LocationID.

Since Seattle has 7 of the total 13 employees, we can guesstimate that just over ½ (or more than 50%) of JProCo employees work in Seattle (LocationID 1). Let’s run the query and check the results.

SQL SERVER - Tips from the SQL Joes 2 Pros Development Series - Advanced Aggregates with the Over Clause - Day 11 of 35 j2p_11_1

Our result set shows no ratios and all 0’s. This is because our calculation involved only integers. (The grant amount data was expressed in decimal form.) Rather than writing additional code using CAST, we’ll use a trick that works with many programming languages. Multiply the numerator by 1.0 to make each figure display as a decimal instead of an integer. Multiply the numerator by 1.0, so results appear as decimals instead of integers.

SQL SERVER - Tips from the SQL Joes 2 Pros Development Series - Advanced Aggregates with the Over Clause - Day 11 of 35 j2p_11_4

This result is a big improvement – each result is now in decimal form. The Seattle occupancy rate is about 53.85%.  Now multiply instead by 100 so the values show as percentages, like we did with the Grant example. In this instance be sure to multiply by 100.0, so the values show as decimals and not integers. 

Finally, polish your report by adding the descriptive title Pct in place of the blank column header. Sort your report in descending order of occupancy (Pct) and LastName.

SQL SERVER - Tips from the SQL Joes 2 Pros Development Series - Advanced Aggregates with the Over Clause - Day 11 of 35 j2p_11_5

Note: If you want to setup the sample JProCo database on your system you can watch this video. For this post you will want to run the SQLQueriesChapter5.0Setup.sql script from Volume 2.

Question 11

Q 11) You have a table named CurrentProducts. The table contains a column named Category. You need to make a T-SQL statement that calculates the percentage (with decimals) of products in each product Category. Which query should you use?

  1. SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts
  2. SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts
  3. SELECT DISTINCT Category,
    COUNT(*) OVER ( )*100.0/ COUNT(*) OVER(PARTITION BY Category) as PctCategory
    FROM CurrentProducts

Rules:

Please leave your answer in comment section below with correct option, explanation and your country of resident.
Every day one winner will be announced from United States.
Every day one winner will be announced from India.
A valid answer must contain country of residence of answerer.
Please check my facebook page for winners name and correct answer.
Winner from United States will get Joes 2 Pros Volume 2.
Winner from India will get Joes 2 Pros Volume 2.
The contest is open till next blog post shows up at which is next day GTM+2.5.

Reference:  Pinal Dave (https://blog.sqlauthority.com)

Joes 2 Pros, SQL Scripts
Previous Post
SQL SERVER – Who needs ETL Version Control?
Next Post
SQL SERVER – SafePeak – The Plug and Play Immediate Acceleration Solution

Related Posts

108 Comments. Leave new

  • Shekhar Gurav.
    August 11, 2011 5:33 pm

    Correct Answer : 2

    SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    Shekhar Gurav.
    Country : INDIA

    Reply
  • In order to achieve the desired results, the second option would be the correct SQL query to use:

    2.SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    Country: United States

    Reply
  • Correct option:-2

    Shilpa
    India

    Reply
  • Mike Michalicek
    August 11, 2011 5:51 pm

    The correct answer is #2

    #1 has *100 and should be *100.0 to get decimals and
    #3 has the overall count in the numerator and the Category count in the denominator which is backwards.

    USA

    Mike Michalicek

    Reply
  • Option : 2 is correct.

    SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    This query will gives the decimal values.
    ————
    Option :1 (Wrong) this query will return only integer values
    Option :2 (Wrong) this query will return without percentage but gives the value of total count over count per category

    Thanks,
    Rajasekar.k
    Bangalore- INDIA

    Reply
  • Option : 2 is correct.

    SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    This query will gives the decimal values.
    ————
    Option :1 (Wrong) this query will return only integer values
    Option :3 (Wrong) this query will return without percentage but gives the value of total count over count per category

    Thanks,
    Rajasekar.k
    Bangalore- INDIA

    Reply
  • Option : 2 Is correct.

    Dhina-Bangalore-India.

    Reply
  • SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    Chetan – USA

    Reply
  • Rajesh Mohanrangan
    August 11, 2011 6:41 pm

    Answer is Option 2

    # SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    because it gives the decimal values as output

    From India

    Reply
  • 2. SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    USA

    Reply
  • Here is how I would make a T-SQL statement that calculates the percentage (with decimals) of products in each product Category.

    SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    The answer is option 2.

    David
    USA

    Reply
  • Prasanna kumar.D
    August 11, 2011 7:34 pm

    Answer for today blog quiz : Option 2

    2) SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    Chennai, TamilNadu, India

    Reply
  • srinivas reddy
    August 11, 2011 7:50 pm

    correct answer is Option# 2
    Country: USA

    Reply
  • I will use the option #2. Option #1 and Option #2 are almost the same except for multiplier of 100.0 vs. 100 in the first case. Using 100.0 we implicitly tell SQL Server to use decimals and not integer math. In SQL Server (and in some other languages) when you divide one integer by another integer you get an integer as a result. So, that’s why the option #1 is not correct.

    Option #3 has the calculation backwards.

    I am from USA

    Reply
  • Jungchan Hsieh
    August 11, 2011 8:45 pm

    #2 is calculates the percentage

    SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    Reply
  • Answer is 2:

    SELECT DISTINCT Category,
    COUNT(*) OVER ( )*100.0/ COUNT(*) OVER(PARTITION BY Category) as PctCategory
    FROM CurrentProducts

    Ramdas,Charlotte,USA

    Reply
  • The correct option is 2

    SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    Option 1 is incorrect because it doesn’t multiply by 1.0 to get the answer in decimal.

    Option 3 is incorrect because it divides the total products by the number of products in the category. This is not the correct calculation.

    Option 2 is correct because it divides the number of products in the categury by the dotal number of products, and uses the *100.0 to ensure that the answer comes out as decimal.

    Country of Residence: USA

    Reply
  • Diljeet kumari
    August 11, 2011 9:27 pm

    Correct answer for the above question is 2 option

    Option 2) SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    Explaining the reason :

    As the Requirement is we need to display percentage (with decimals) of products in each product Category needing first to find two things
    A. No of product in particular category
    B. Total no of products in the table
    and the requirement is that we need the result in decimal point so we have to use COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as clearly explained by you.

    Diljeet kumari
    INDIA

    Reply
  • Hi Pinal,

    Challenge:
    Q 11) You have a table named CurrentProducts. The table contains a column named Category. You need to make a T-SQL statement that calculates the percentage (with decimals) of products in each product Category. Which query should you use?

    1.SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts
    2.SELECT DISTINCT Category,
    COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts
    3.SELECT DISTINCT Category,
    COUNT(*) OVER ( )*100.0/ COUNT(*) OVER(PARTITION BY Category) as PctCategory
    FROM CurrentProducts

    Correct Answer:
    The correct answer is #2:
    SELECT DISTINCT Category, COUNT(*) OVER (PARTITION BY Category)*100.0/ COUNT(*) OVER() as PctCategory
    FROM CurrentProducts

    Explanation:
    Items #1 will not give you the resultant PctCategory in decimals since you are dividing with an integer.

    Item #3 is giving you the percentage that is greater than 100%.

    The correct answer is #2.

    Country:
    United States

    Thanks for the knowledge!

    Regards,

    Bill Pepping

    Reply
  • Answer is Option #2….we have to use 100.0 in order to get decimals, so option #1 is out, and Option #3 does not give what we want either.

    Thomas Riehle
    USA

    Reply

Leave a Reply