Is this a valid SQL query? - sql

This is just an example, I'm doing something similar that is going to grab thousands of records.
SELECT * FROM
(SELECT * FROM zoodb) As TblA
INNER JOIN
(SELECT animal_ID, Max(checkup_year) AS latest_checkup FROM TblA GROUP BY animal_ID) as TblB
ON (TblA.animal_ID = TblB.animal_ID) AND (TblA.checkup_year = TblB.latest_checkup)
Basically in this, I want to grab the records only for the latest checkup year

Your query is not valid.
But you can do it this way:
SELECT * FROM zoodb z
INNER JOIN (SELECT animal_ID, Max(checkup_year) AS latest_checkup
FROM zoodb
GROUP BY animal_ID) aux ON aux.animal_ID = z.animal_ID AND aux.latest_checkup = z.checkup_year

SELECT * FROM
(SELECT * FROM zoodb) As TblA
....
There is no need for this sub query. The FROM in the outer query can handle it!
SELECT *
FROM zoodb AS TblA
...
The rest looks fine!
Edit:
As aF pointed out you cannot reference TblA from the inner join subquery (See aF's answer).

aF.'s answer is correct, but I thought I'd propose a solution that expresses your intention a little more clearly:
select *
from zoodb as TblA
where latest_checkup = (
select max(latest_checkup)
from zoodb
where animal_id = TblA.animal_id);
The lack of the [inner join (subselect)] also means that it won't get too messy if you need to add additional constraints in the future.

Also the query optimizer prefers inner joins to nested select statements, so you'll get a more optional execution plan

Related

SQL: Issue with WHERE Clause

SELECT DISTINCT Interests.Interest_name, Impressions.Count
FROM Interests
WHERE Vertical_name = 'Retail'
INNER JOIN Impressions ON Interests.Interest_Name = Impressions.Interest_Name;
The above query generates the error
Lookup Error - SQL Server Database Error: Incorrect syntax near the keyword 'Inner'.
If I remove the WHERE clause it works perfectly OK. I am not sure if there is an issue with the syntax?
WHERE condition needs to go after joins, try to move it to the end:
SELECT DISTINCT Interests.Interest_name,Impressions.Count FROM Interests
Inner Join Impressions ON Interests.Interest_Name = Impressions.Interest_Name
WHERE Vertical_name = 'Retail';
Well the Syntax is just wrong. You have to move the WHERE after your JOIN
For example:
SELECT DISTINCT Interests.Interest_name,Impressions.Count
FROM Interests
INNER JOIN Impressions
ON Interests.Interest_Name = Impressions.Interest_Name
WHERE Vertical_name = 'Retail';
If you tried to pre-filter your table Interests you can do that this way:
SELECT DISTINCT Interests.Interest_name,Impressions.Count
FROM (
SELECT *
FROM Interests
WHERE Vertical_name = 'Retail'
) as Interests
INNER JOIN Impressions
ON Interests.Interest_Name = Impressions.Interest_Name;
Just a hint after all. I would suggest you, to use aliases for every table. It will improve the reading and will save you if you need to rename a table.
The where goes after the from clause. And join is part of the from clause.
Your query would be easier to write and to read with aliases:
SELECT DISTINCT i.Interest_name, i.Count
FROM Interests i Inner Join
Impressions im
ON i.Interest_Name = im.Interest_Name;
WHERE Vertical_name = 'Retail';
If you don't need the DISTINCT, then you should remove it. It only hurts performance.
In fact, a better way to write this query is to use a correlated subquery:
SELECT DISTINCT i.Interest_name, i.Count
FROM Interests i
WHERE EXISTS (SELECT 1
FROM Impressions im
WHERE i.Interest_Name = im.Interest_Name
)
WHERE i.Vertical_name = 'Retail';
This assumes that Vertical_Name is in Interests. Otherwise, it would go in the subquery.

Opposite of UNION SQL Query

I have 2 tables :
interests (storing the interest ID and name)
person_interests(storing the person_id and interest_id)
How do I select all the interests that a particular person has not selected?
I have tried the following SQL Query and am still not getting the desired result
SELECT *
FROM interests LEFT JOIN person_interests
ON interests.id=person_interests.person_id
WHERE person_interests.id IS NULL
AND person_id=66;
Use NOT EXISTS
SELECT *
FROM interests
WHERE NOT EXISTS (
SELECT person_interests.interest_id
FROM person_interests
WHERE person_id = 66
AND interests.id = person_interests.interest_id
)
SELECT * from interests
WHERE interest_id NOT IN
(SELECT interest_id FROM person_interests WHERE person_id=66)
There are a couple things going on.
First, I think you have an error in your join. Shouldn't it be interests.id=person_interests.interest_id instead of interests.id=person_interests.person_id?
That aside, I still don't think you would be getting the desired result because your person_id filter is on the RIGHT side of your LEFT OUTER join, thus turning it back into an inner join. There are several ways to solve this. Here's what I would probably do:
SELECT *
FROM
(SELECT interests.*, person_id
FROM interests LEFT JOIN person_interests
ON interests.id=person_interests.interest_id
WHERE person_interests.id IS NULL )
WHERE person_id=66;

Select Combination of columns from Table A not in Table B

I have two sets of table with all the contacts on an Account their titles and etc. For data migration purposes I need to select All ContactsIds with their AccountID from Table A that do not exist in TableB. Its the combination of both the ContactId and the AccountID. I have tried the following:
Select * from Final_Combined_Result wfcr
WHERE NOT EXISTS (Select Contact_ID, Account_ID from Temp_WFCR)
I know this is completely off, but I have looked at a couple of other questions on here but was unable to find an appropriate solution.
I have also tried this:
Select * from Final_Combined_Result wfcr
WHERE NOT EXISTS
(Select Contact_ID, Account_ID from Temp_WFCR as tc
where tc.Account_ID=wfcr.Account_InternalID
AND tc.Account_ID=wfcr.Contact_InternalID)
This seems to be correct but I would like to make sure.
Select wfcr.ContactsId, wfcr.AccountID
from Final_Combined_Result wfcr
left join Temp_WFCR t_wfcr ON t_wfcr.ContactsIds = wfcr.ContactsId
AND t_wfcr.AccountID = wfcr.AccountID
WHERE t_wfcr.AccountID is null
See this great explanation of joins
#juergend's answer shows the left join.
Using a not exists you join in the subselect, it would look like this:
Select wfcr.*
from
Final_Combined_Result wfcr
WHERE NOT EXISTS
(Select 1 --select values dont matter here, only the join restricts.
from
Temp_WFCR t
where t.Contact_ID = wfcr.Contact_InternalID
and t.account_id = wfcr.Account_InternalID
)

SQL IN query from multiple tables

SELECT DISTINCT addresses.email FROM addresses
WHERE addresses.user_id IN (SELECT user_group.id_user_groups FROM user_group
WHERE id_group_groups IN (SELECT news_group.groupid_newsg FROM news_group
WHERE newsid_news_good=1))
The above mentioned SQL query is not executing! It gets hanged until I stop the query. I have tried SQL operator "UNION" after first SELECT statement, but it displays all the email addresses which does not belong to a group. I want to select only those email addresses of the users who belong to "id_group_groups =5" (pls see the query below ) and are subscribed to "newsid_news_good=1".
The following query runs perfectly fine:
SELECT DISTINCT addresses.email FROM addresses
WHERE addresses.user_id IN (SELECT user_group.id_user_groups FROM user_group
WHERE id_group_groups =5 )
Does anybody have an idea what is the problem with the first query? Help will be strongly appreciated!
I think the sub selects complicate your problem. If I understand it right, it would be easier to solver your problem using joins instead of sub selects.
Try out something like this:
SELECT DISTINCT addresses.email
FROM addresses
JOIN user_group
ON user_group.id_user_groups = adresses.USER_ID
JOIN news_group
ON news_group.groupid_newsg = user_group.id_group_groups
WHERE newsid_news_good = 1
SELECT DISTINCT addresses.email FROM addresses
INNER JOIN (
SELECT user_group.id_user_groups FROM user_group
INNER JOIN news_group
ON news_group.groupid_newsg = id_group_groups
WHERE newsid_news_good=1
)
ON user_group.id_user_groups = addresses.user_id
You want to use joins. The subqueries you are using are most likely the cause of your performance woes.
SELECT DISTINCT a.email
FROM addresses a
INNER JOIN user_group u ON u.id_user_groups AND u.id_group_groups = 5
INNER JOIN news_group n ON n.groupid_newsg = u.id_group_groups AND n.newsid_news_good = 1
I'm going to guess that you are using MySQL, because it does a really poor job of executing subqueries in unions. The canonical way to fix this is to change them to exists with correlated subqueries:
SELECT DISTINCT a.email
FROM addresses a
where exists (select 1
from user_group ug
where ug.id_user_groups = a.user_id and
exists (select 1
from news_group ng
where ng.newsid_news_good = 1 and
ng.groupid_news = ug.id_group_groups
)
)
This solution works in all databases, of course; it is much more efficient in MySQL. Assuming email is not repeated in the addresses table, then you can drop the outer distinct.
The alternatives with join are also feasible. However they require the distinct.

SQL 2005 - The column was specified multiple times

I am getting the following error when trying to run this query in SQL 2005:
SELECT tb.*
FROM (
SELECT *
FROM vCodesWithPEs INNER JOIN vDeriveAvailabilityFromPE
ON vCodesWithPEs.PROD_PERM = vDeriveAvailabilityFromPE.PEID
INNER JOIN PE_PDP ON vCodesWithPEs.PROD_PERM = PE_PDP.PEID
) AS tb;
Error: The column 'PEID' was specified multiple times for 'tb'.
I am new to SQL.
The problem, as mentioned, is that you are selecting PEID from two tables, the solution is to specify which PEID do you want, for example
SELECT tb.*
FROM (
SELECT tb1.PEID,tb2.col1,tb2.col2,tb3.col3 --, and so on
FROM vCodesWithPEs as tb1 INNER JOIN vDeriveAvailabilityFromPE as tb2
ON tb1.PROD_PERM = tb2.PEID
INNER JOIN PE_PDP tb3 ON tb1.PROD_PERM = tb3.PEID
) AS tb;
That aside, as Chris Lively cleverly points out in a comment the outer SELECT is totally superfluous. The following is totally equivalent to the first.
SELECT tb1.PEID,tb2.col1,tb2.col2,tb3.col3 --, and so on
FROM vCodesWithPEs as tb1 INNER JOIN vDeriveAvailabilityFromPE as tb2
ON tb1.PROD_PERM = tb2.PEID
INNER JOIN PE_PDP tb3 ON tb1.PROD_PERM = tb3.PEID
or even
SELECT *
FROM vCodesWithPEs as tb1 INNER JOIN vDeriveAvailabilityFromPE as tb2
ON tb1.PROD_PERM = tb2.PEID
INNER JOIN PE_PDP tb3 ON tb1.PROD_PERM = tb3.PEID
but please avoid using SELECT * whenever possible. It may work while you are doing interactive queries to save typing, but in production code never use it.
Looks like you have the column PEID in both tables: vDeriveAvailabilityFromPE and PE_PDP. The SELECT statement tries to select both, and gives an error about duplicate column name.
You're joining three tables, and looking at all columns in the output (*).
It looks like the tables have a common column name PEID, which you're going to have to alias as something else.
Solution: don't use * in the subquery, but explicitly select each column you wish to see, aliasing any column name that appears more than once.
Instead of using * to identify collecting all of the fields, rewrite your query to explicitly name the columns you want. That way there will be no confusion.
just give new alias name for the column that repeats,it worked for me.....