I'm doing something like:
SELECT T1.NAME, T2.DATE
FROM T1
INNER JOIN
(
SELECT * FROM OTHERTABLE
) AS T2 ON T2.USERID = T1.USERID
Which works, but if I query the alias table, I get an error saying that T2 is an invalid object name.
Example:
SELECT
T1.NAME,
T2.DATE,
CASE
WHEN EXISTS (SELECT TOP 1 1 FROM T2 WHERE T2.THISFIELD = T1.THISFIELD) THEN 'HELLO'
ELSE 'BYE'
END AS COMMENT -- THIS ALSO FAILS
FROM T1
INNER JOIN
(
SELECT * FROM OTHERTABLE
) AS T2 ON T2.USERID = T1.USERID
WHERE (SELECT COUNT(*) FROM T2) > 0
I thought that's what I did, "create" T2. Is there any way I can use T2 like such ?
My goal is to scrape all the related data from OTHERTABLE once because I'll have many CASE in the SELECT clause depending whether data exists in T2 or not. I don't want to do EXISTS for every field since that'll launch a new query in a huge table everytime.
Your query using a sub-query of SELECT * FROM OTHERTABLE which doesn't make sense. You can modify it like;
SELECT
T1.NAME,
T2.DATE,
...
FROM T1
JOIN OTHERTABLE T2 ON T2.USERID = T1.USERID
WHERE (SELECT COUNT(*) FROM OTHERTABLE ) > 0
You cannot use a sub-query multiple times in the same query. Instead use a Common Table Expression (CTE) for that purpose. T2 is a CTE in the following example.
;WITH T2 AS
(
SELECT UserId, col1, col2, [Date]
FROM OtherTable
)
SELECT T1.NAME, T2.DATE
FROM T1
JOIN T2 ON T2.USERID = T1.USERID
WHERE (SELECT COUNT(*) FROM T2) > 0
Related
Is there a way to display only records where one email corresponds to more than 3 names?
I have tried the code below, but it does not return anything.
SELECT
t1.Name, t2.Email
FROM
Table1 t1
JOIN Table2 t2 on t1.ID=t2.PersonID
GROUP BY
t1.Name, t2.Email
HAVING COUNT(t2.Email) > 3
If your version supports window function then you can do :
select t.*
from (select t1.name, t2.email,
count(t2.email) over (partition by t1.name) as cnt
from t1 inner join
t2
on t2.personid = t1.id
) t
where cnt > 3;
I think you want:
SELECT t1.Name, GROUP_CONCAT(t2.Email)
FROM Table1 t1 JOIN
Table2 t2
ON t1.ID = t2.PersonID
GROUP BY t1.Name
HAVING COUNT(t2.Email) > 3;
The big change is to the GROUP BY -- this does not have EMAIL. You seem to want the emails returns on each row, so this concatenates them together.
EDIT:
In SQL Server, you would use string_agg():
SELECT t1.Name, STRING_AGG(t2.Email, ',')
FROM Table1 t1 JOIN
Table2 t2
ON t1.ID = t2.PersonID
GROUP BY t1.Name
HAVING COUNT(t2.Email) > 3;
Or, if you want individual rows:
SELECT n.*
FROM (SELECT t1.Name, t2.Email,
COUNT(*) OVER (PARTITION BY t1.Name) as cnt
FROM Table1 t1 JOIN
Table2 t2
ON t1.ID = t2.PersonID
) n
WHERE cnt > 3
ORDER BY Name;
SELECT table1.*
,address
,job
FROM table1
JOIN table2 ON table2.name = table1.name
The above query returns result for duplicate values of name too. How can I convert the query to get only one value for distinct values of name column?
I am using SQL Server
You can easily accomplish this with row_number window function. See query below:
select t1.id, t1.name, t1.pets, t2.address, t2.job
from (
select *,
row_number() over (partition by [name] order by id) rn
from Table1
) t1
join table2 t2 on t1.name = t2.name
where t1.rn = 1
I would recommend a lateral join -- apply -- for this purpose:
SELECT t1.*, t2.address, t2.job
FROM table2 t2 CROSS APPLY
(SELECT t1.*
FROM table1 t1
WHERE t2.name = t1.name
) t1;
Normally, the subquery would have an ORDER BY to specify the ordering. Otherwise the result is indeterminate.
This is often faster than using window functions for this purpose.
I have following query-
select * from
Table1 t1 , table2 t2 ,
(select idCol from table3) t3
My question is - Can I use table t2 inside subquery?
like this
select * from
Table1 t1 , table2 t2 ,
(select idCol, t2.nameCol from table3) t3
Obviously this gives error invalid identifier t2.nameCol
But if I write as follows, it give unnecessaru extra rows
select * from
Table1 t1 , table2 t2 ,
(select idCol, t2.nameCol from table3, table2 t2) t3
any other way to do this?
EDIT
Basically what I am trying to achieve is following
select * from
Table1 t1 , table2 t2 ,
(select
case
when t2.nameCol = 'ABC' then 'ABC'
else idCol
end idCol from table3) t3
To join a table only when certain criteria is met is called an outer join. Here is how:
select *
from table1 t1
inner join table2 t2 on <join criteria here>
left outer join table3 t3 on t2.namecol <> 'ABC' and <join criteria here>;
It may suffice in your case, however, to move the subquery to your SELECT clause:
select
t1.*,
t2.*,
case when t2.namecol = 'ABC' then
'ABC'
else
(select idcol from table3 t3 where <join criteria here>)
end
from table1 t1
inner join table2 t2 on <join criteria here>;
You can try below. I am sure you have some kind of join between t1 and t2. IN such case, you can add same at the end of the statement.
SELECT t1.*,
t2.*,
( SELECT CASE
WHERE t2.nameco1 = 'ABC' THEN 'ABC'
ELSE idcol
END idcol
FROM table3) idcol
FROM table1 t1,
table2 t2
My problem here is that i'm modifying an existing query and i cannot use count(*) in the query.
I have to use inner join subqueries.
What i need to "transform" into my inner join is like this (this works):
SELECT count(distinct t1.id)
FROM table1 t1
WHERE t1.column1 = 'value1' AND
t2.column2 = 'value2' AND
EXISTS(select 1 from table2 t2 where t2.id = t1.id)
My global query looks like this:
SELECT [many many column]
FROM table2 t2
INNER JOIN [...]
LEFT OUTER JOIN [...]
--[I NEED MY COUNT HERE, see below for example]
WHERE [some conditions are true]
ORDER BY [some column]
What i found to help me is something like this:
SELECT [many many column], myJoin.Count
FROM table2 t2
INNER JOIN (
SELECT tt2.id, count(distinct tt2.id) as Count
FROM table2 tt2
WHERE EXISTS (SELECT 1 FROM table1 tt1 where tt1.id = tt2.id)
GROUP BY tt2.id) myJoin
on t2.id = myJoin.id;
See what i'm trying to acheive? I need to count the ids, joining 2 tables, but i can't have a count in my main query, i can't possibly copy-paste all the "group by" condition that would go with it...
I'm on sql server.
If i find the answer i will come back and post it.
Thanks for any advice/tricks about this.
How about the following:
SELECT table2.*, TopQ.MyCount
FROM (
SELECT t2.id, myJoin.MyCount
FROM table2 t2
INNER JOIN (
SELECT tt2.id, count(distinct tt2.id) as MyCount
FROM table2 tt2
WHERE EXISTS
(SELECT 1 FROM table1 tt1 where tt1.id = tt2.id)
GROUP BY tt2.id) AS myJoin
on t2.id = myJoin.id
)AS TopQ
INNER JOIN table2 ON TopQ.id = table2.id
I came across this:
select count(distinct t1.id) over (partition by t1.aColumn) as myCount,
[many many column]
from table2 t2
inner join table1 t1 on [someConditions] = value1 and
[someConditions] = value2 and
t2.id = t1.id;
I get the same results as my first select i posted in my question, and without adding a "group by" anywhere and a lot of inner join that im not that familliar with. I'm gonna stick with this solution.
Thanks!
I need to run a query where one of the fields returned is a yes or no if there is a row in another table matching one of the key fields in the first table.
Sounds like a job for join, except the second table is one to many and I just need to know if there are zero or a non zero number of rows in the secondary table.
I could do something like this:
select t1.name, t1.id, (select count(1) from t2 where t1.id=t2.id) from t1
but I'd like to avoid making an aggregate subquery if possible.
It was mentioned to me that I could use the exists() function, but I'm not seeing how to do that in a select field.
This is sybase 15 by the way.
You could still do the JOIN, something like this:
SELECT t1.name, t1.id, CASE WHEN t2.id IS NULL THEN 0 ELSE 1 END Existst2
FROM t1
LEFT JOIN (SELECT id FROM t2 GROUP BY id) t2
ON t1.id = t2.id
ahhh, I got it from another stackoverflow quetion...
case when exists (select * from t2 where t1.id = t2.id) then 1 else 0 end
I am just writing down the syntax here:
if exists (select * from table1 t1 inner join table1 t2 on t1.id = t2.id )
select * from table2
How about this query ( Work with all databases )
select t1.name, t1.id, 'Y' as HasChild
from t1
where exists ( select 1 from t2 where t2.id = t1.id)
UNION
select t1.name, t1.id, 'N' as HasChild
from t1
where NOT exists ( select 1 from t2 where t2.id = t1.id)