Alias in Where clauses and Join on clauses - sql

I thought using an alias in the WHERE clause and JOIN ON clause is illegal because of the logical execution sequence. These two clauses are before the SELECT so the alias is not defined.
However, I read two codes lately they had an alias in these two clauses and they ran without problems.
SELECT w1.id
FROM weather AS w1
JOIN weather AS w2 ON DATEDIFF(w1.recordDate, w2.recordDate) = 1
AND w1.Temperature > w2.Temperature;
This is on leetcode, using an alias in the JOIN clause.
SELECT o.OrderID, o.OrderDate, c.CustomerName
FROM Customers AS c, Orders AS o
WHERE c.CustomerName = 'Around the Horn'
AND c.CustomerID = o.CustomerID;
This is on W3school, using an alias in the Where clause.
Now, I am confused about the restrictions of using an alias. Any thoughts?

I think you are confusing column aliases and table aliases.
Table aliases are defined in the FROM clause. As a best practice, they should always be used to reference to column names. In your first example, w1 and w2 are table aliases and w1.temperature and w2.temperature are qualified column references.
A column alias is defined in the SELECT clause:
select 'this is a ' as column_alias
The column_alias cannot be used in the ON or WHERE clauses associated with the SELECT.

Related

Knex query error "pollers.description\" must appear in the GROUP BY clause or be used in an aggregate function"

So I have 2 tables(pollers and errors) I am trying to join on where pollers.id = errors.poller_id and then count the number of errors a poller has using the pollers.id. I used:
knex.raw(`select poller_name, description, count(pollers.id) as "poller_errors"
from pollers
inner join
errors on pollers.id = errors.poller_id
group by poller_name`)
it came up with an error "pollers.description\" must appear in the GROUP BY clause or be used in an aggregate function"
The error seems pretty clear. As a general rule, the unaggregated columns in the select need to be in the group by. So just put them there:
select poller_name, description, count(pollers.id) as "poller_errors"
from pollers inner join
errors
on pollers.id = errors.poller_id
group by poller_name, description;
That said, there is one important exception to this, which goes by the fancy name of "functional dependency". You can aggregate by a primary or unique key and use other columns from the same table. I am guessing that pollers.id is a unique key. If so, you could write this as:
select p.poller_name, p.description, count(*) as poller_errors
from pollers p inner join
errors e
on p.id = e.poller_id
group by p.id;
Note the other changes to this code:
All column references are qualified, so it is clear to you, the compiler, and anyone who reads the code where they are coming from.
Table abbreviations are used for the aliases.
The double quotes are removed from the column aliases. Don't get in the habit of escaping column references.

JOIN or not in SQL statement

Suppose I have a SELECT statement, and I use table name such as :
select cust.name from cust,order where cust.id = order.id ;
I didn't use a JOIN statement,
Question is the given statement is JOIN or not?
Yes it is a join statement.When you want to perform a join you have to select all required tables.
When you select all required tables in From and use join , in WHERE it becomes implicit join as below.
select
cust.name
from customer c, [order] o
where c.id = o.id ;
When you use join two tables with JOIN syntax then it is called explicit join as below
select
cust.name
from customer c
join [order] o
on c.id = o.id ;
You seem to be trying to write a join query using the implicit join syntax. That should look something like this:
select cust.name from cust, order where cust.id = order.id;
But actually, order is a reserved keyword in just about every version of SQL, so you should escape it, maybe using double quotes:
select cust.name from cust, "order" where cust.id = "order".id;
However, it is much preferable to use modern, explicit join syntax now, so please use:
select cust.name from cust inner join "order" on cust.id = "order".id;
And consider renaming your order table to something other than a reserved keyword.
The , is an archaic way of writing JOINs in SQL. It basically means CROSS JOIN, although the semantics are slightly different in the FROM clause.
It was replaced in the 1990's -- yes, the last millennium -- by proper, explicit, standard, readable JOIN syntax. As much as I dislike commas, they are part of the SQL language. I do wish they would be deprecated, but that has not yet occurred (that would mean that newer databases would have no obligation to support the syntax).
I think you know that you should be using:
select c.name
from cust c join
order o
on c.id = o.id ;
(An aside, order is a really bad name for a table because it is an Oracle keyword.)
The word "join" can mean multiple things when talking about databases.
It can mean the JOIN operator, which is a specific operator in the FROM clause.
It can mean the "join" operation in the FROM clause. By this definition, , is a "join" operation, which is equivalent to CROSS JOIN.
It can mean the combining of data from any multiple tables -- basically using underlying "join" algorithms. By this definition, IN, EXISTS, and so on might be "join" operations, even though they are not in the FROM clause.

Inner Join Invalid Object Name

Trying to do a simple inner join query but keep getting errors
Select Alias from Db.SchmaName.Customers as Customer
Select Alias from Db.SchmaName.Orders as Order
Inner Join Order on Customer.Alias = Order.Alias
The Db and SchmaNames are both exactly the same but Alias column is different between the 2 tables.
Both of the select statements work as expected but the error for the Inner Join is
"Invalid object name 'Order'"
I get this error even if I do not use the table alias and instead type out the full path to the table
I'm surprised that's the error you're getting. ORDER is a reserved word in SQL Server, don't use it for your object and alias names, you should be getting the error:
Incorrect syntax near 'order'.
Don't use reserved words (or even key words really) for object names, or if you have to, quote them ([Order]). Personally I would do:
SELECT Alias --This is missing an alias as well, so would be ambigous
FROM Db.SchmaName.Orders O
INNER JOIN Customer C ON C.Alias = O.Alias;
Aliases are great for making your SQL succinct. Aliasing the table Customers as Customer, doesn't really do that. A lot of people (like myself), tend to use a few characters to alias a table. So, for Customer I used C. Personally, I tend to use the letters of specific words in the object's name. For example, if I have a table called StockItem I would probably use SI. For a table I have called ic_BD_HPT1 I use HPT1.
Those are two queries, not one.
Select Alias from Db.SchmaName.Customers as Customer
Select Alias from Db.SchmaName.Orders as Order
Inner Join Order on Customer.Alias = Order.Alias
Is actually
Select Alias from Db.SchmaName.Customers as Customer;
Select Alias from Db.SchmaName.Orders as Order
Inner Join Order on Customer.Alias = Order.Alias;
The second query is invalid, as it tries to join the Order alias to itself.
To join two tables you need to specify the tables themselves in the FROM, JOIN statements. If you want to select a column that exists in both tables you have to explicitly specify which one you want, eg:
Select Order.Alias
from Db.SchmaName.Orders as [Order]
Inner Join Db.SchmaName.Customers as Customer
on Customer.Alias = [Order].Alias;
ORDER is a keyword which means you need to either enclose it in square brackets or use a better alias. In fact, Orders is just fine :
Select Orders.Alias
from Db.SchmaName.Orders
Inner Join Db.SchmaName.Customers as Customer
on Customer.Alias = Orders.Alias;
use different table alias name rather key word of SQL(Order),another issue Alias column is exist in your both table so use table.column in selection and
your join need like below
Select Customer.Alias from Db.SchmaName.Customers as Customer
inner join Db.SchmaName.Orders as O
on Customer.Alias = O.Alias
Order is a Keyword in SQL. You can not use Keywords in SQL for aliases, except if you put [] around the alias.
I would use a different name for the alias.
There are two queries in your question.
This is one
Select Alias from Db.SchmaName.Customers as Customer
And this is the second one
Select Alias from Db.SchmaName.Orders as Order
Inner Join Order on Customer.Alias = Order.Alias
The error you are getting is on the second query,
You are trying to JOIN against the Alias you've given to the table Orders, i.e ORDER. What you should do instead is reference the Alias on the ON clause, like so
Select Order.Alias, Customer.Alias
from Db.SchmaName.Orders as Order
INNER JOIN Db.SchmaName.Customers as Customer on Order.Alias = Customer.Alias

Using SQL Alias vs Inner Join, what is the difference?

In http://www.w3schools.com/sql/sql_alias.asp, it mentions using alias to do the following query,
SELECT
Orders.OrderID, Orders.OrderDate, Customers.CustomerName
FROM
Customers, Orders
WHERE
Customers.CustomerName = "Around the Horn"
AND Customers.CustomerID = Orders.CustomerID;
This confuses me with the usage of JOIN. Isn't this kind of query joining the columns from two tables? What are the differences between this kind of query and JOIN?
JOIN and alias are two differnt concept .. the alias is for create a substitutive name (shorter usually) for a more easy object reference and for a more easy read .. so you can have column name alias or table name alias eg:
select a.col1
from my_table as a
a is an alias for the table my_table
or
select a.col1 as c1
from my_table as a
where c1 is an alias for col1
JOIN are for build relation between table
The Join can be implict or explict
In your code you are using implici join and the condition between the tables that keep the relation is based on where clause
but you could use a more espressive way using explict join
SELECT Orders.OrderID, Orders.OrderDate, Customers.CustomerName
FROM Customers
INNER JOIN Orders on Customers.CustomerID=Orders.CustomerID;
WHERE Customers.CustomerName="Around the Horn"
Both the same, there is no difference.
There are differences only in readability.
In my opinion, PLSQL(ORACLE) developer choosing alias when writing queries then TSQL(SQL Server) developer choosing by Join
The answer to your question is there is no difference between your query and an inner join but many times, your write queries between tables where the relationships are not explicitly defined or a table may not require a relationship. In those cases, you would use a left join to return data from a first table and zero to many items from the table on the right. Using your format, makes that a lot more difficult to write and read. As for table Aliases, when writing self joins for example, you will need to use them so understanding them is essential.

SQL query performance issues

I have the below SQL query that is taking an inordinate amount of time to run. Indexes have been added to all of the join fields in each table. Record counts for each table are as follows:
CRM.ASSET_PLUS:15,766,000
CRM.EMPLOYEE: 44,300
CRM.ACCOUNT: 1,180,000
CRM.DATA_NOTIFICATIONS: 500
CRM.PROD_INT: 87,800
What can I do to make this query more efficient?
SELECT D.NAME AS UP_ACCOUNT_NAME,
B.FIRST_NAME,
B.LAST_NAME
FROM CRM.ASSET_PLUS A,
CRM.EMPLOYEE B,
CRM.ACCOUNT C,
CRM.ACCOUNT D,
CRM.DATA_NOTIFICATIONS E,
CRM.PROD_INT F
WHERE A.STATUS IN ('Active', 'Pending Install')
AND E.PROD_DEF_OLD = F.X_ITEM_NUMBER
AND F.ROW_ID = A.PRODUCT_ID
AND C.UP_ACCOUNT_ID = D.ACCOUNT_ID
AND C.ACCOUNT_ID = A.LOCATION_ACCOUNT_ID
AND D.MANAGER_ID = B.EMPLOYEE_ID
AND UPPER(D.NAME) LIKE '%BP%'
GROUP BY D.NAME,
B.FIRST_NAME,
B.LAST_NAME
Get rid off that group by.
You are just selecting (account join employee) and using all other tables to filter it. You can get duplicated result and that's the only reason why you are using that group by.
But that's not necessary if you rewrite the query to move all other tables to the where clause.
I created a example to demonstrate it.
and try to write explicit joins to separate filter and join predicates.
example using SQL fiddle
1)
Get rid of this if you can:
AND UPPER(D.NAME) LIKE '%BP%'
1.1)If posible, do Not allow user to put % in front of a like clause (because it implies full table scan)
Note: You can allow it if you use only one at the beginning, by storing a computed column with reverse(d.name) and using D.reversedname LIKE 'PB%' instead of D.name like 'BP%' . The key here is that the % must be in the end and not in the beginning.
Check this out
https://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning
create index for d.name
1.2 do NOT use UPPER -> either:
->change the column collation to a case insensitive one (ending in _CI) and remove the UPPER (easier)
or
->use a computed column to precalculate this UPPER(D.NAME) in a new PERSISTED column and use that column instead in the clause. If you use this solution, do not forget to create an index for that new column.
2) create indexes for all foreign keys used in the query / joins
3) if possible , require minimum chars for that LIKE, in order to reduce the number of possible results.
First thing that I see here is that you use INNER JOIN and then WHERE statement.
Use syntax table1 as t1 INNER JOIN table2 as t2 ON t1.key = t2.key.
So in where you will have only UPPER(D.NAME) LIKE '%BP%' AND A.STATUS IN ('Active', 'Pending Install') condition. It will allow DBMS to do lots of optimizations.
Also instead of INNER JOIN try to do LEFT JOIN where it possible. It will significantly decrease amount of rows in temp table.