Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Why your query returns two rows</strong></p> <p>To understand why your query returns two rows instead of the one you expect, it helps to understand the logical steps that SQL Server theoretically takes when executing your query.</p> <p>The first logical step is to process the FROM clause. Your query specifies a cross join between the two tables <code>dbo.Test1</code> and <code>dbo.corr_table</code> to produce an intermediate virtual table (let's call it <code>V1</code>) containing 8 rows:</p> <pre><code>ID COUNTRY PERIODKEY A B C FIELD VALUE START_DATE END_DATE 1 E 201201 1 5 9 a 4 201201 201202 1 E 201202 1 5 9 a 4 201201 201202 3 G 201203 3 7 11 a 4 201201 201202 4 H 201204 4 8 12 a 4 201201 201202 1 E 201201 1 5 9 b 6 201201 201202 1 E 201202 1 5 9 b 6 201201 201202 3 G 201203 3 7 11 b 6 201201 201202 4 H 201204 4 8 12 b 6 201201 201202 </code></pre> <p>The second logical step is to process the WHERE clause. Your query specifies that only rows with an ID of 1, a Country of 'E', and a PeriodKey of 201201 should pass. Two rows in the intermediate table meet this condition to populate another intermediate table (let's call it <code>V2</code>):</p> <pre><code>ID COUNTRY PERIODKEY A B C FIELD VALUE START_DATE END_DATE 1 E 201201 1 5 9 a 4 201201 201202 1 E 201201 1 5 9 b 6 201201 201202 </code></pre> <p>The third and final logical step is to process the SELECT clause. Your query specifies that two new columns <code>a</code> and <code>b</code> should be computed based on values in existing columns, and that all the columns from table <code>dbo.Test1</code> should be returned unmodified. The SELECT clause is basically a list of columns that defines the structure of the result set. It does not control how many rows are in the result set. This intermediate table (let's call it <code>V3</code>) is the same as the result set:</p> <pre><code>a b id Country PeriodKey a b c 4 5 1 E 201201 1 5 9 1 6 1 E 201201 1 5 9 </code></pre> <p>The two rows in <code>V2</code> both contain elements of the single row that you expect to see in your result set. All the columns from the base table <code>dbo.Test1</code> contain the same value, because the values in these columns were copied from just one row in <code>dbo.Test1</code>. The values in the first columns <code>a</code> and <code>b</code> are copied from two different rows in <code>dbo.corr_table</code>.</p> <p>If we were able to group these two rows in <code>V2</code> together, we could make one row that matches our expectations. Fortunately, we can express this easily in SQL.</p> <p><strong>How to produce your expected result set</strong></p> <p>In SQL, A SELECT statement has the GROUP BY clause that groups multiple rows into one row that represents the group. Logically, it is processed after the WHERE clause and before the SELECT clause.</p> <p>To your query I added a GROUP BY clause and invoked an aggregate function for each of the computed columns. This query produces your expected result:</p> <pre><code>SELECT MAX( CASE WHEN dbo.corr_table.Field = 'a' THEN dbo.corr_table.Value END ) AS corr_a, MAX( CASE WHEN dbo.corr_table.Field = 'b' THEN dbo.corr_table.Value END ) AS corr_b, dbo.Test1.* FROM dbo.Test1 INNER JOIN dbo.corr_table ON dbo.Test1.id = dbo.corr_table.id WHERE dbo.Test1.id = 1 and dbo.Test1.Country = 'E' and dbo.Test1.PeriodKey in (201201) GROUP BY dbo.Test1.id, dbo.Test1.Country, dbo.Test1.PeriodKey, dbo.Test1.a, dbo.Test1.b, dbo.Test1.c; </code></pre> <p>I have no more time to explain just now, but I will expand my answer later with an explanation of why this works. For now, I recommend that you read about logical query processing and the SELECT statement. Itzik Ben-Gan published a helpful <a href="http://www.sql.co.il/books/insidetsql2008/Logical%20Query%20Processing%20Poster.pdf" rel="nofollow noreferrer">PDF flow chart</a> explaining the logical steps. It is reproduced as an image below, copied from <a href="http://sqlwithmanoj.wordpress.com/2010/10/28/sql-logical-query-processing-order/" rel="nofollow noreferrer">sqlwithmanoj.wordpress.com</a>:</p> <p><img src="https://i.stack.imgur.com/SqryD.jpg" alt="enter image description here"></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload