Referring to a column alias in two tables - sql

I have two hive SQL tables which consist of following columns.
table_1
|customer_id | ip_address|
region_table
|country_name | region_name|
I tried,
SELECT table_1.customer_id, table_1.ip_address, getCountry(ip_address) AS Country, region_table.region_name FROM table_1 JOIN region_table ON region_table.country_name = Country;
getCountry() is UDF which returns the country name when the IP address
is passed into it. I want to use that country name to create another
column with the corresponding region from the region_table. And i want
to get the following table as my output.
customer_id | ip_address | Country | region_name
Any thoughts on what I'm missing in my query?

select c.customer_id
,c.ip_address
,getCountry(c.ip_address) as Country
,r.region_name
from table_1 c
join region_table r
on r.country_name =
getCountry(c.ip_address)

In case of Oracle, you can not refer column alias defined in SELECT statement in WHERE clause of same query!! Because database engine first evaluates WHERE clause and identifies eligible rows and then proceeds to fetch columns as defined in SELECT part of query.
In your case, right query should be
select
table_1.customer_id,
table_1.ip_address,
getCountry(ip_address) AS Country,
region_table.region_name
FROM table_1
JOIN region_table ON region_table.country_name = getCountry(table_1 .ip_address);

Related

sql select record with lowest value of the two

Despite my internet searching, I've not found a solution to what I think is a simple SQL problem.
I have a simple table as such:
zip | location | transit
------------------------
10001 | 1 | 5
10001 | 2 | 2
This table of course has a large number of zip codes, but I'd like to make s simple query by zip code and instead of returning all rows with the zip, return only a single row (with all 3 columns), that contains the lowest transit value.
I've been playing with the aggregate function min(), but haven't gotten it right.
Using Postgres SQL DB 9.6
Thanks!
Use ORDER BY along with LIMIT :
SELECT t.*
FROM mytable t
WHERE t.zipcode = ?
ORDER BY t.transit
LIMIT 1
How about
select * from table where zip = ‘10001’ order by transit limit 1
I would use distinct on:
select distinct on (zip) t.*
from t
order by zip, transit;
This is usually the most efficient method in Postgres, particularly with an index on (zip, transit).
Of course if you have only one zip code that you care about, then where/order by/limit is also totally reasonable.
Assuming that you also want to return the location value associated with the minimum transit value, then here is one possible solution using an inner join:
select t.*
from
yourtable t inner join
(select u.zip, min(u.transit) as mt from yourtable u group by u.zip) v
on t.zip = v.zip and t.transit = v.mt
Change all references to yourtable to the name of your table.

Why won't this query update the field with the lookup?

I'm trying to run the following query to update one table from another. The dates and email address work and carry across, but the nested query I'm using to get Subject_1 from a reference table does not. What am I doing wrong?
SELECT
FirstRegistered As SignUpdate,
(SELECT Subj_ClusName FROM tblSubjectLookup INNER JOIN PAD_ApplicantLost2000 ON tblSubjectLookup.Subj_Name=PAD_ApplicantLost2000.raw_subj_interest_1) AS Subject_1,
Email_Address
FROM PAD_ApplicantLost2000
The origin table, PAD_ApplicantLost2000, has a 'raw subject' column which contains, for example, 'Biology'. There is another table, tblSubjectLookup, which has codes for all subjects, so Subj.Name has 'Biology' and 'Subj_ClusName' has 'B1', which is what needs to go in my target table. However, the Subject_1 field in the target table does not populate.
What am I doing wrong?
Why not just use a WHERE clause instead of joining the table again. I also added LIMIT 1 just to make sure only 1 value is returned.
SELECT
FirstRegistered As SignUpdate,
(SELECT Subj_ClusName FROM tblSubjectLookup WHERE tblSubjectLookup.Subj_Name = PAD_ApplicantLost2000.raw_subj_interest_1 LIMIT 1) AS Subject_1,
Email_Address
FROM PAD_ApplicantLost2000
Another, possibly better, way to do it would just be to join the table directly.
SELECT
FirstRegistered As SignUpdate,
Subj_ClusName AS Subject_1,
Email_Address
FROM PAD_ApplicantLost2000
LEFT JOIN tblSubjectLookup ON tblSubjectLookup.Subj_Name = PAD_ApplicantLost2000.raw_subj_interest_1

Joining tables on multiple conditions

I have a little problem - since im not very experienced in SQL - about joining the same table on multiple values. Imagine there is table 1 (called Strings):
id value
1 value1
2 value2
and then there is table 2 (called Maps):
id name description
1 1 2
so name is reference into the Strings table, as is description. Without the second field referencing the Strings table it would be no problem, id just do an inner join on Strings.id = Maps.name. But now id like to obtain the actual string also for description. What would be the best approach for a SELECT that returns me both? Right now it looks like this:
SELECT Maps.id, Strings.value AS mapName FROM Maps INNER JOIN Strings ON Strings.id = Maps.name;
But that obviously only covers one of the localized names. Thank you in advance.
You can do this with two joins to the same table:
SELECT m.id, sname.value AS mapName, sdesc.value as description
FROM Maps m INNER JOIN
Strings sname
ON sname.id = m.name INNER JOIN
Strings desc
ON sdesc.id = m.description;
Note the use of table aliases to distinguish between the two tables.
As long as you want to get a single value from another table, you can use subqueries to do these lookups:
SELECT id,
(SELECT value FROM Strings WHERE id = Maps.name) AS name,
(SELECT value FROM Strings WHERE id = Maps.description) AS description
FROM Maps

Join on two dis-similar column

I need to join one column of a table to a column of another table.
Now these two column consists the geographic region data. But the issue is the column dont have exactly same strings od data.
For ex. Latin America in one column and LATM in another.
The data is table if had been same string would be the simplest joins but these two mean the same but then are different strings . What do I use to accomplish my task.
I need to do is
Select * from Table1 Inner Join Table2 on table1.region = table2.region
You would need to create a mapping table which maps every possible region in Table1.region to every possible region in Table2
for example your Mapping table be like.
MappingTable
--------------------------
Region1 | Region 2
--------------------------
Latin America | LATM
Europe | EUR
.....
The you can create a join like
Select *
from
Table1
inner join
MappingTable
on
Table1.region = MappingTable.Region1
inner join
Table2
on
MappingTable.Region2 = Table2.region
You need to make another table which contains information of TWO table Joining like 'Latin America' = 'LATM' and then have to use this table in join.

SQL left joining tables with ambiguous column names

I need to left join a few tables in a query where the column names are ambiguous.
ListingCategory_Listings:
ID | ListingCategoryID | ListingID | ..
SiteTree_Live:
ID | ClassName | Title | Content | ..
ListingCategory:
ID | IconID
File:
ID | ClassName | Name | Title | Filename | ..
I have the query:
SELECT * FROM ListingCategory_Listings
LEFT JOIN Listing ON ListingCategory_Listings.ListingID = Listing.ID
LEFT JOIN SiteTree_Live ON Listing.ID = SiteTree_Live.ID
LEFT JOIN ListingCategory ON ListingCategory_Listings.ListingCategoryID = ListingCategory.ID
LEFT JOIN File ON ListingCategory.IconID = File.ID
Both the listing and listing category data is stored in the SiteTree_Live table, when my records are returned, obviously, the Title, ID, Content and other ambiguous fields are returned under the heading Title, ID, Content.
I need to access both the Listing Title and The Listing Category Title and other specific information. If they had their data stored in different tables I could use select Listing.Title AS lTitle but how can I do something similar in this situation?
You need to alias the columns and give them different labels.
You should always put only the fields you need into the SELECT clause, listing each individually rather than using *.
Good practice also dictates giving each table a short alias.
SELECT L.Title Listing_Title, LC.Title ListingCategory_Title,
... all your other columns ...
FROM ListingCategory_Listings LCL
LEFT JOIN Listing L ON LCL.ListingID = L.ID
LEFT JOIN SiteTree_Live STL ON L.ID = STL.ID
LEFT JOIN ListingCategory LC ON LCL.ListingCategoryID = LC.ID
LEFT JOIN File F ON LC.IconID = F.ID
I suggest that to ALIAS a COLUMN name, the previous information may not be correct.
The proper syntax for COLUMN ALIAS is :
SELECT column_name AS alias_name
FROM table_name;
In a COLUMN ALIAS, the COLUMN alias assignment is declared beside the proper COLUMN name.
The proper syntax for TABLE ALIAS is :
SELECT column_name(s)
FROM table_name AS alias_name;
In a TABLE ALIAS, the TABLE alias is put beside the column being selected in the SELECT portion of the statement. The TABLE ALAIS assignment is made in the FROM portion of the statement.
The difference being that the alias assignment is made beside the proper name of what is desired to be ALIASED!
I set up a practice on the Fraser's provided example & it worked for me. I believe the answer provided was speaking of TABLE ALIAS, not COLUMN ALIAS.
I disagree with ALIAS usage where the TABLE or COLUMN ALIAS is so short that it complicates the readability of the code. I believe it should be short, but not so short that the code is not 'self documenting' for maintenance purposes. That is my 2¢ of thought on it!