what is the difference between these two sql statements
a) select * from T1,T2 where T1.A=T2.A ;
b) select * from T1,T2 where T2.A=T1.A ;
I am getting the same output in both cases,is there any differences between both statements?
c) select * from T1 inner join T2 on T1.A=T2.A ;
What is the diffence between Statement C and a?in that case also getting the same output as of a and b...
Can Inner Joins also be written as sql statement a?
They are all essentially different ways to join two tables using the same join condition.
Between 1 and 2, there is absolutely no difference as far as the database is concerned.
The last option is the standardized join syntax - this is what you should be using in order to ensure your SQL is readable - this is what people reading your SQL will expect to see when you join tables.
All are the same there is no difference
These are diiferent ways
SQL is like mathematics that way; equality is symmetric. If A = B, then B = A. There should be no difference.
The JOIN/ON notation is just another way to write the same thing. The notation is different to emphasize the join visually.
The output tells you the answer better than any number of SO users will. Why don't you believe your own eyes?
(a) and (c) are same except the second is ANSI-92 SQL syntax and the first is the older SQL syntax which didn't incorporate the join clause. They should produce exactly the same internal query plan, although you may like to check.
You should use the ANSI-92 syntax for several of reasons
The use of the JOIN clause separates the relationship logic from the
filter logic (the WHERE) and is thus cleaner and easier to
understand.
It doesn't matter with this particular query, but there are a few
circumstances where the older outer join syntax (using + ) is
ambiguous and the query results are hence implementation dependent -
or the query cannot be resolved at all. These do not occur with
ANSI-92
It's good practice as most developers and dba's will use ANSI-92
nowadays and you should follow the standard. Certainly all modern
query tools will generate ANSI-92.
Related
I have my business-logic in ~7000 lines of T-SQL stored procedures, and most of them has next JOIN syntax:
SELECT A.A, B.B, C.C
FROM aaa AS A, bbb AS B, ccc AS C
WHERE
A.B = B.ID
AND B.C = C.ID
AND C.ID = #param
Will I get performance growth if I will replace such query with this:
SELECT A.A, B.B, C.C
FROM aaa AS A
JOIN bbb AS B
ON A.B = B.ID
JOIN ccc AS C
ON B.C = C.ID
AND C.ID = #param
Or they are the same?
The two queries are the same, except the second is ANSI-92 SQL syntax and the first is the older SQL syntax which didn't incorporate the join clause. They should produce exactly the same internal query plan, although you may like to check.
You should use the ANSI-92 syntax for several of reasons
The use of the JOIN clause separates
the relationship logic from the
filter logic (the WHERE) and is thus
cleaner and easier to understand.
It doesn't matter with this particular query, but there are a few circumstances where the older outer join syntax (using + ) is ambiguous and the query results are hence implementation dependent - or the query cannot be resolved at all. These do not occur with ANSI-92
It's good practice as most developers and dba's will use ANSI-92 nowadays and you should follow the standard. Certainly all modern query tools will generate ANSI-92.
As pointed out by #gbn, it does tend to avoid accidental cross joins.
Myself I resisted ANSI-92 for some time as there is a slight conceptual advantage to the old syntax as it's a easier to envisage the SQL as a mass Cartesian join of all tables used followed by a filtering operation - a mental technique that can be useful for grasping what a SQL query is doing. However I decided a few years ago that I needed to move with the times and after a relatively short adjustment period I now strongly prefer it - predominantly because of the first reason given above. The only place that one should depart from the ANSI-92 syntax, or rather not use the option, is with natural joins which are implicitly dangerous.
The second construct is known as the "infixed join syntax" in the SQL community. The first construct AFAIK doesn't have widely accepted name so let's call it the 'old style' inner join syntax.
The usual arguments go like this:
Pros of the 'Traditional' syntax: the
predicates are physically grouped together in the WHERE clause in
whatever order which makes the query generally, and n-ary relationships particularly, easier to read and understand (the ON clauses of the infixed syntax can spread out the predicates so you have to look for the appearance of one table or column over a visual distance).
Cons of the 'Traditional' syntax: There is no parse error when omitting one of the 'join' predicates and the result is a Cartesian product (known as a CROSS JOIN in the infixed syntax) and such an error can be tricky to detect and debug. Also, 'join' predicates and 'filtering' predicates are physically grouped together in the WHERE clause, which can cause them to be confused for one another.
The two queries are equal - the first is using non-ANSI JOIN syntax, the 2nd is ANSI JOIN syntax. I recommend sticking with the ANSI JOIN syntax.
And yes, LEFT OUTER JOINs (which, btw are also ANSI JOIN syntax) are what you want to use when there's a possibility that the table you're joining to might not contain any matching records.
Reference: Conditional Joins in SQL Server
OK, they execute the same. That's agreed.
Unlike many I use the older convention. That SQL-92 is "easier to understand" is debatable. Having written programming languages for pushing 40 years (gulp) I know that 'easy to read' begins first, before any other convention, with 'visual acuity' (misapplied term here but it's the best phrase I can use).
When reading SQL the FIRST thing you mind cares about is what tables are involved and then which table (most) defines the grain. Then you care about relevant constraints on the data, then the attributes selected. While SQL-92 mostly separates these ideas out, there are so many noise words, the mind's eye has to interpret and deal with these and it makes reading the SQL slower.
SELECT Mgt.attrib_a AS attrib_a
,Sta.attrib_b AS attrib_b
,Stb.attrib_c AS attrib_c
FROM Main_Grain_Table Mgt
,Surrounding_TabA Sta
,Surrounding_tabB Stb
WHERE Mgt.sta_join_col = Sta.sta_join_col
AND Mgt.stb_join_col = Stb.stb_join_col
AND Mgt.bus_logic_col = 'TIGHT'
Visual Acuity!
Put the commas for new attributes in front It makes commenting code easier too
Use a specific case for functions and keywords
Use a specific case for tables
Use a specific case for attributes
Vertically Line up operators and operations
Make the first table(s) in the FROM represent the grain of the data
Make the first tables of the WHERE be join constraints and let the specific, tight constraints float to the bottom.
Select 3 character alias for ALL tables in your database and use the alias EVERYWHERE you reference the table. You should use that alias as a prefix for (many) indexes on that table as well.
6 of 1 1/2 dozen of another, right? Maybe. But even if you're using ANSI-92 convention (as I have and in cases will continue to do) use visual acuity principles, verticle alignment to let your mind's eye avert to the places you want to see and and easily avoid things (particularly noise words) you don't need to.
Execute both and check their query plans. They should be equal.
In my mind the FROM clause is where I decide what columns I need in the rows for my SELECT clause to work on. It is where a business rule is expressed that will bring onto the same row, values needed in calculations. The business rule can be customers who have invoices, resulting in rows of invoices including the customer responsible. It could also be venues in the same postcode as clients, resulting in a list of venues and clients that are close together.
It is where I work out the centricity of the rows in my result set. After all, we are simply shown the metaphor of a list in RDBMSs, each list having a topic (the entity) and each row being an instance of the entity. If the row centricity is understood, the entity of the result set is understood.
The WHERE clause, which conceptually executes after the rows are defined in the from clause, culls rows not required (or includes rows that are required) for the SELECT clause to work on.
Because join logic can be expressed in both the FROM clause and the WHERE clause, and because the clauses exist to divide and conquer complex logic, I choose to put join logic that involves values in columns in the FROM clause because that is essentially expressing a business rule that is supported by matching values in columns.
i.e. I won't write a WHERE clause like this:
WHERE Column1 = Column2
I will put that in the FROM clause like this:
ON Column1 = Column2
Likewise, if a column is to be compared to external values (values that may or may not be in a column) such as comparing a postcode to a specific postcode, I will put that in the WHERE clause because I am essentially saying I only want rows like this.
i.e. I won't write a FROM clause like this:
ON PostCode = '1234'
I will put that in the WHERE clause like this:
WHERE PostCode = '1234'
ANSI syntax does enforce neither predicate placement in the proper clause (be that ON or WHERE), nor the affinity of the ON clause to adjacent table reference. A developer is free to write a mess like this
SELECT
C.FullName,
C.CustomerCode,
O.OrderDate,
O.OrderTotal,
OD.ExtendedShippingNotes
FROM
Customer C
CROSS JOIN Order O
INNER JOIN OrderDetail OD
ON C.CustomerID = O.CustomerID
AND C.CustomerStatus = 'Preferred'
AND O.OrderTotal > 1000.0
WHERE
O.OrderID = OD.OrderID;
Speaking of query tools who "will generate ANSI-92", I'm commenting here because it generated
SELECT 1
FROM DEPARTMENTS C
JOIN EMPLOYEES A
JOIN JOBS B
ON C.DEPARTMENT_ID = A.DEPARTMENT_ID
ON A.JOB_ID = B.JOB_ID
The only syntax that escapes conventional "restrict-project-cartesian product" is outer join. This operation is more complicated because it is not associative (both with itself and with normal join). One have to judiciously parenthesize query with outer join, at least. However, it is an exotic operation; if you are using it too often I suggest taking relational database class.
I have my business-logic in ~7000 lines of T-SQL stored procedures, and most of them has next JOIN syntax:
SELECT A.A, B.B, C.C
FROM aaa AS A, bbb AS B, ccc AS C
WHERE
A.B = B.ID
AND B.C = C.ID
AND C.ID = #param
Will I get performance growth if I will replace such query with this:
SELECT A.A, B.B, C.C
FROM aaa AS A
JOIN bbb AS B
ON A.B = B.ID
JOIN ccc AS C
ON B.C = C.ID
AND C.ID = #param
Or they are the same?
The two queries are the same, except the second is ANSI-92 SQL syntax and the first is the older SQL syntax which didn't incorporate the join clause. They should produce exactly the same internal query plan, although you may like to check.
You should use the ANSI-92 syntax for several of reasons
The use of the JOIN clause separates
the relationship logic from the
filter logic (the WHERE) and is thus
cleaner and easier to understand.
It doesn't matter with this particular query, but there are a few circumstances where the older outer join syntax (using + ) is ambiguous and the query results are hence implementation dependent - or the query cannot be resolved at all. These do not occur with ANSI-92
It's good practice as most developers and dba's will use ANSI-92 nowadays and you should follow the standard. Certainly all modern query tools will generate ANSI-92.
As pointed out by #gbn, it does tend to avoid accidental cross joins.
Myself I resisted ANSI-92 for some time as there is a slight conceptual advantage to the old syntax as it's a easier to envisage the SQL as a mass Cartesian join of all tables used followed by a filtering operation - a mental technique that can be useful for grasping what a SQL query is doing. However I decided a few years ago that I needed to move with the times and after a relatively short adjustment period I now strongly prefer it - predominantly because of the first reason given above. The only place that one should depart from the ANSI-92 syntax, or rather not use the option, is with natural joins which are implicitly dangerous.
The second construct is known as the "infixed join syntax" in the SQL community. The first construct AFAIK doesn't have widely accepted name so let's call it the 'old style' inner join syntax.
The usual arguments go like this:
Pros of the 'Traditional' syntax: the
predicates are physically grouped together in the WHERE clause in
whatever order which makes the query generally, and n-ary relationships particularly, easier to read and understand (the ON clauses of the infixed syntax can spread out the predicates so you have to look for the appearance of one table or column over a visual distance).
Cons of the 'Traditional' syntax: There is no parse error when omitting one of the 'join' predicates and the result is a Cartesian product (known as a CROSS JOIN in the infixed syntax) and such an error can be tricky to detect and debug. Also, 'join' predicates and 'filtering' predicates are physically grouped together in the WHERE clause, which can cause them to be confused for one another.
The two queries are equal - the first is using non-ANSI JOIN syntax, the 2nd is ANSI JOIN syntax. I recommend sticking with the ANSI JOIN syntax.
And yes, LEFT OUTER JOINs (which, btw are also ANSI JOIN syntax) are what you want to use when there's a possibility that the table you're joining to might not contain any matching records.
Reference: Conditional Joins in SQL Server
OK, they execute the same. That's agreed.
Unlike many I use the older convention. That SQL-92 is "easier to understand" is debatable. Having written programming languages for pushing 40 years (gulp) I know that 'easy to read' begins first, before any other convention, with 'visual acuity' (misapplied term here but it's the best phrase I can use).
When reading SQL the FIRST thing you mind cares about is what tables are involved and then which table (most) defines the grain. Then you care about relevant constraints on the data, then the attributes selected. While SQL-92 mostly separates these ideas out, there are so many noise words, the mind's eye has to interpret and deal with these and it makes reading the SQL slower.
SELECT Mgt.attrib_a AS attrib_a
,Sta.attrib_b AS attrib_b
,Stb.attrib_c AS attrib_c
FROM Main_Grain_Table Mgt
,Surrounding_TabA Sta
,Surrounding_tabB Stb
WHERE Mgt.sta_join_col = Sta.sta_join_col
AND Mgt.stb_join_col = Stb.stb_join_col
AND Mgt.bus_logic_col = 'TIGHT'
Visual Acuity!
Put the commas for new attributes in front It makes commenting code easier too
Use a specific case for functions and keywords
Use a specific case for tables
Use a specific case for attributes
Vertically Line up operators and operations
Make the first table(s) in the FROM represent the grain of the data
Make the first tables of the WHERE be join constraints and let the specific, tight constraints float to the bottom.
Select 3 character alias for ALL tables in your database and use the alias EVERYWHERE you reference the table. You should use that alias as a prefix for (many) indexes on that table as well.
6 of 1 1/2 dozen of another, right? Maybe. But even if you're using ANSI-92 convention (as I have and in cases will continue to do) use visual acuity principles, verticle alignment to let your mind's eye avert to the places you want to see and and easily avoid things (particularly noise words) you don't need to.
Execute both and check their query plans. They should be equal.
In my mind the FROM clause is where I decide what columns I need in the rows for my SELECT clause to work on. It is where a business rule is expressed that will bring onto the same row, values needed in calculations. The business rule can be customers who have invoices, resulting in rows of invoices including the customer responsible. It could also be venues in the same postcode as clients, resulting in a list of venues and clients that are close together.
It is where I work out the centricity of the rows in my result set. After all, we are simply shown the metaphor of a list in RDBMSs, each list having a topic (the entity) and each row being an instance of the entity. If the row centricity is understood, the entity of the result set is understood.
The WHERE clause, which conceptually executes after the rows are defined in the from clause, culls rows not required (or includes rows that are required) for the SELECT clause to work on.
Because join logic can be expressed in both the FROM clause and the WHERE clause, and because the clauses exist to divide and conquer complex logic, I choose to put join logic that involves values in columns in the FROM clause because that is essentially expressing a business rule that is supported by matching values in columns.
i.e. I won't write a WHERE clause like this:
WHERE Column1 = Column2
I will put that in the FROM clause like this:
ON Column1 = Column2
Likewise, if a column is to be compared to external values (values that may or may not be in a column) such as comparing a postcode to a specific postcode, I will put that in the WHERE clause because I am essentially saying I only want rows like this.
i.e. I won't write a FROM clause like this:
ON PostCode = '1234'
I will put that in the WHERE clause like this:
WHERE PostCode = '1234'
ANSI syntax does enforce neither predicate placement in the proper clause (be that ON or WHERE), nor the affinity of the ON clause to adjacent table reference. A developer is free to write a mess like this
SELECT
C.FullName,
C.CustomerCode,
O.OrderDate,
O.OrderTotal,
OD.ExtendedShippingNotes
FROM
Customer C
CROSS JOIN Order O
INNER JOIN OrderDetail OD
ON C.CustomerID = O.CustomerID
AND C.CustomerStatus = 'Preferred'
AND O.OrderTotal > 1000.0
WHERE
O.OrderID = OD.OrderID;
Speaking of query tools who "will generate ANSI-92", I'm commenting here because it generated
SELECT 1
FROM DEPARTMENTS C
JOIN EMPLOYEES A
JOIN JOBS B
ON C.DEPARTMENT_ID = A.DEPARTMENT_ID
ON A.JOB_ID = B.JOB_ID
The only syntax that escapes conventional "restrict-project-cartesian product" is outer join. This operation is more complicated because it is not associative (both with itself and with normal join). One have to judiciously parenthesize query with outer join, at least. However, it is an exotic operation; if you are using it too often I suggest taking relational database class.
We have a Oracle 10g and most of our applications are running Oracle Forms 6i. I found that all of the queries written in views/packages/procedures/functions are JOINING tables at WHERE clause level. Example
SELECT * FROM
TABLE_A A,
TABLE_B B,
TABLE_C C,
TABLE_D D
WHERE
A.ID=B.ID(+)
AND B.NO=C.NO(+)
AND C.STATUS=D.ID
AND C.STATUS NOT LIKE 'PENDING%'
This query applies only to ORACLE since it has the (+) join qualifier which is not acceptable in other SQL platforms. The above query is equivalent to:
SELECT * FROM
TABLE_A A LEFT JOIN TABLE_B B ON A.ID=B.ID
LEFT JOIN TABLE_C C ON B.NO=C.NO
JOIN TABLE_D D ON C.STATUS=D.ID
WHERE
C.STATUS NOT LIKE 'PENDING%'
Non of the queries I have seen is written with join taking place in the FROM clause.
My question can be divided into three parts:
Q: Assuming that I have the same Oracle environment, which query is better in terms of performance, cache, CPU load, etc. The first one (joining at WHERE) or the second (joining at FROM)
Q: Is there any other implementation of SQL that accepts the (+) join qualifier other than oracle? if yes, which?
Q: Maybe having the join written at WHERE clause makes the query more readable but compromises the ability to LEFT/RIGHT join, that's why the (+) was for. Where can I read more about the origin of this (+) and why it was invented specifically to Oracle?
Q1. No difference. You can check it using profiling and compare execution plan.
Q2. As I know, only oracle support it. But it is not recommended to use in latest version of Oracle RDBMS:
Oracle recommends that you use the FROM clause OUTER JOIN syntax
rather than the Oracle join operator. Outer join queries that use the
Oracle join operator (+) are subject to the following rules and
restrictions, which do not apply to the FROM clause OUTER JOIN syntax:
Q3. Oracle "invent" (+) before outer join was specified in SQL ANSI.
There should be no performance difference. Assuming you're on a vaguely recent version of Oracle, Oracle will implicitly convert the SQL 99 syntax to the equivalent Oracle-specific syntax. Of course, there are bugs in all software so it is possible that one or the other will perform differently because of some bug. The more recent the version of Oracle, the less likely you'll see a difference.
The (+) operator (and a variety of other outer join operators in other databases) were created because the SQL standard didn't have a standard way of expressing an outer join until the SQL 99 standard. Prior to then, every vendor created their own extensions. It took Oracle a few years beyond that to support the new syntax. Between the fact that bugs were more common in the initial releases of SQL 99 support (not common but more common than they are now), the fact that products needed to continue to support older database versions that didn't support the new syntax, and people being generally content with the old syntax, there is still plenty of code being written today that uses the old Oracle syntax.
A1:
As far as I know they vary in-terms of syntax not in performance. So there is no difference between joining at 'where' clause and joining at 'from' clause.
A2:
To answer this in better way, 'Joining at FROM' clause is standard across all the platforms. So forget about (+) symbols
A3
I have worked in Oracle for sometimes. People use (+) symbols for left/right join because it's easy to write. Some ppl use join at (FROM) clause because it's more readable and understandable.
Hope these points helps you. Please let me know incase am wrong with anything.
One difference between Oracle syntax and ANSI syntax is:
In Oracle syntax you cannot make a FULL OUTER JOIN, there you have to use ANSI syntax.
Oracle introduced ANSI syntax in Oracle 9i - including several bugs. In the meantime since Oracle 11 or 12 it works quite well, but you may discover some obstacles in Oracle 9/10.
Another advandage of ANSI Join syntax is you cannot forget any join condition.
"SELECT * FROM TABLE_A, TABLE_B" performs implicitly a Cross-Join. "SELECT * FROM TABLE_A JOIN TABLE_B" raise an error, you are forced to provide the join condition. If you want to Cross-Join you have to specify it, i.e. "SELECT * FROM TABLE_A CROSS JOIN TABLE_B"
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
WHERE clause better execute before IN and JOIN or after
INNER JOIN versus WHERE clause — any difference?
What, if any, are the differences between the following?
Select
col1,
col2
from TableA A, TableB B
where A.ID = B.ID
and
Select
col1,
col2
From TableA A
Inner Join TableB B on A.ID = B.ID
They seem to have the same behaviors in SQL,
They will likely be optimized to the same thing by the RDBMS. They both JOIN the tables on the A.ID = B.ID criteria.
However, the JOIN syntax is explicit and considered correct.
The former is ANSI-89 syntax, and the latter is ANSI-92 syntax. The latter should almost always be used due to the fact that it's much clearer when you start to use outer joins when expressed in ANSI-92 syntax.
The first syntax is (as you pointed out) a cross join or Cartesian product of the two tables. In a system with no optimizer (or a poor optimizer) this will produce a combination of every record in the first table combined with every record in the second table, then filter them down to just those matching the WHERE clause.
The output from both statements will be the same, and if the system you are using has a good optimizer than the performance will be the same as well.
Two comments I would offer:
1) I find it better to be explicit about your intent when writing statements. If you intended to perform an INNER JOIN then use the INNER JOIN syntax. Future you 6 months form now will be thankful.
2) The optimizer in SQL Server will perform an INNER JOIN in this situation (at least recent versions, can't guarantee all versions), but how well it guesses that path is going to depend on the version of the SQL Server engine and is not guaranteed to remain the same in the future (I doubt it will change in this situation, but is the cost of a few more characters of typing really that high?)
#ypercube correctly pointed out your question is about two different INNER JOIN syntaxes. You don't have any outer join syntax. As #Matt Whitfield pointed out, the first syntax is ANSI-92 and the second one is ANSI-89 style. I agree with matt entirely that in more complicated queries the ANSI-92 syntax is way way more readable.
Furthermore, depending on your version of SQL Server THE ANSI-89 syntax is DEPRECATED and can give you problems. See SR0010: Avoid using deprecated syntax when you join tables or views In fact, in the next version SQL 2011, or Denali, or whatever we're calling it, the ANSI-89 syntax will not be supported. See: Features Not Supported in the Next Version of SQL Server
(search for the word "join").
Do these two queries differ from each other?
Query 1:
SELECT * FROM Table1, Table2 WHERE Table1.Id = Table2.RefId
Query 2:
SELECT * FROM Table1 INNER JOIN Table2 ON Table1.Id = Table2.RefId
I analysed both methods and they clearly produced the same actual execution plans. Do you know any cases where using inner joins would work in a more efficient way. What is the real advantage of using inner joins rather than approaching the manner of "Query 1"?
The two statements you have provided are functionally equivalent to one another.
The variation is caused by differing SQL syntax standards.
For a really exciting read, you can lookup the various SQL standards by visiting the following Wikipedia link. On the right hand side are references and links to the various dialects/standards of SQL.
http://en.wikipedia.org/wiki/SQL
These SQL statements are synonymous, though specifying the INNER JOIN is the preferred method and follows ISO format. I prefer it as well because it limits the plumbing of joining the tables from your where clause and makes the goal of your query clearer.
These will result in an identical query plan, but the INNER JOIN, OUTER JOIN, CROSS JOIN keywords are prefered because they add clarity to the code.
While you have the ability to specifiy join hints using the keywords in the FROM clause, you can do more complicated joins in the WHERE clause. But otherwise, there will be no difference in query plan.
I will also add that the first syntax is much more subject to inadvertent cross joins as the queries get complicated. Further the left and right joins in this syntax do not work properly in SQL server and should never be used. Mixing the syntax when you add a left join can also cause problems where the query does not correctly return the results. The syntax in the first example has been outdated for 17 years, I see no reason to ever use it.
Query 1 is considered an old syntax style and its use is discouraged. You will run into problems with you use LEFT and Right joins using that syntax style. Also on SQL Server you can have problems mixing those two different syles together in queries that use view of different formats.
I have found a significant difference using the LEFT OUTER JOINS and putting the conditions on the joined table in the ON clause rather than the WHERE clause. Once you put a condition on the joined table in the WHERE clause, you defeat the left outer join.
When I was using Oracle, I used the archaic (+) after the joined table (with all conditions including join conditions in the WHERE clause)because that's what I knew. When we became a SQL Server shop, I was forced to use LEFT OUTER JOINs, and I found they didn't work as before until I discovered this behavior. Here's an example:
select NC.*,
IsNull(F.STRING_VAL, 'NONE') as USER_ID,
CO.TOTAL_AMT_ORDERED
from customer_order CO
INNER JOIN VTG_CO_NET_CHANGE NC
ON NC.CUST_ORDER_ID=CO.ID
LEFT OUTER JOIN USER_DEF_FIELDS F
ON F.DOCUMENT_ID = CO.ID and
F.PROGRAM_ID='VMORDENT' and
F.ID='UDF-0000072' and
F.DOCUMENT_ID is not null
where NC.acct_year=2017