Performing a sum on rows with condition - sql

I am trying to create a query like this
select sum(t1.quantity) - sum(t2.quantity * SELECT CASE WHEN (condition on t3.status) THEN 1 ELSE 0 END) ),0)
from table1 t1
inner join table2 t2 on t1.key = t2.key
inner join table3 t3 on t2.key = t3.key
Basically what it do is a subtraction between the first some and a second some of t2.quantity that are in rows that have a condition on the column t3.status (for example t3.status > 2).
But I am getting
Cannot perform an aggregate function on an expression containing an
aggregate or a subquery.
Is there a way to do this without adding extra join or other query?

I think this is what you are trying to do. You don't need a select again when using case as t3 is already joined.
select sum(t1.quantity) - sum(t2.quantity * CASE WHEN t3.status > 2 THEN 1 ELSE 0 END)
from table1 t1
inner join table2 t2 on t1.key = t2.key
inner join table3 t3 on t2.key = t3.key

Related

SQL query to fetch data based on column value

Is it possible to get entire data in one attempt for this scenario? I have this query where I need retrieve product name from another table.
SELECT T1.CASE_ID,
T2.PRODUCT_ID,
T2.LEVEL,
(CASE WHEN T2.LEVEL = 3 THEN T3.PARENT_PRODUCT_ID
WHEN T2.LEVEL = 2 THEN T2.PRODUCT_ID
WHEN T2.LEVEL = 1 THEN NULL END) AS NEW_PRODUCT_ID,
T3.PRODUCT_NAME
FROM TABLE1 T1
LEFT OUTER JOIN TABLE2 T2
ON T1.CASE_ID = T2.CASE_ID
LEFT OUTER JOIN TABLE3 T3
ON T2.PRODUCT_ID=T3.PRODUCT_ID
Right now the T3.PRODUCT_NAME return value based on T2.PRODUCT_ID but what I really need is to able to retrieve data based on the value from NEW_PRODUCT_ID?
Here is my expected output:
Hope this makes sense.
You can use a subquery
SELECT T4.CASE_ID, T4.PRODUCT_ID, T4.LEVEL, T4.NEW_PRODUCT_ID, T5.PRODUCT_NAME
FROM (
SELECT T1.CASE_ID,
T2.PRODUCT_ID,
T2.LEVEL,
(CASE WHEN T2.LEVEL = 3 THEN T3.PARENT_PRODUCT_ID
WHEN T2.LEVEL = 2 THEN T2.PRODUCT_ID
WHEN T2.LEVEL = 1 THEN NULL END) AS NEW_PRODUCT_ID,
T3.PRODUCT_NAME
FROM TABLE1 T1
LEFT OUTER JOIN TABLE2 T2
ON T1.CASE_ID = T2.CASE_ID
LEFT OUTER JOIN TABLE3 T3
ON T2.PRODUCT_ID=T3.PRODUCT_ID
) AS T4
LEFT OUTER JOIN TABLE3 T5
ON T4.NEW_PRODUCT_ID=T5.PRODUCT_ID

SQL Multiple subquery issue

Currently struggling with a second subquery (t3) which is giving me a syntax error. The query works fine if t3 is excluded.
SELECT switch(LEFT(t1.[treatment],1)='C',"Complaint",LEFT(t1.[treatment],1)='P',"Post") AS Treatment, count(t1.[ID]) AS Total_Vol, count(t2.[event]) AS Total_Posted, format(count(t2.[event]) / count(t1.[ID]),"0.00%") AS Percentage, COUNT(IIF(t1.[requirements]='1',1,)) AS Special _Population,count(t3.[approved]) as Approved_vol
FROM Main_audit_table_v3 AS t1 LEFT JOIN (SELECT t2.[ID], t2.[event] FROM Main _table AS t2 WHERE t2.event Not Like ('NA')) AS t2 ON t1.[ID] = t2.[ID]
LEFT JOIN (SELECT t3.[ref],t3.[requirement],t3.[approved] from Main_table AS t3 where
t3.[requirement] = '1' and t3.[approved] not like ('NA')) as t3
t2.[ID] = t3.[ID]
GROUP BY LEFT(t1.[treatment],1);
The expected output is that the [approved] column will provide a count of records where requirement = 1 and approved not like NA.
In MS Access you need additional parentheses for JOINs. And you are missing ON:
SELECT . . .
FROM (Main_audit_table_v3 AS t1 LEFT JOIN
(SELECT t2.[ID], t2.[event]
FROM Main _table AS t2
WHERE t2.event Not Like ('NA')
) AS t2 ON t1.[ID] = t2.[ID]
) LEFT JOIN
(SELECT t3.[ref], t3.[requirement], t3.[approved]
FROM Main_table AS t3
WHERE t3.[requirement] = '1' and t3.[approved] not like 'NA'
) as t3
ON t2.[ID] = t3.[ID]
GROUP BY LEFT(t1.[treatment], 1);

Search record from one table in other table and receive info about this

In T1 I have a 50 ID'ss. I'm trying to find which ones are in T2. And add row name "test" next to ID with info about occurrence in T2. But when I put my code I receive only ID's which are included in T2. What I`m doing wrong?
SELECT DISTINCT t1.id, CASE WHEN t1.id IS NULL THEN 0 ELSE 1 END AS test
FROM t2
JOIN t1 ON t2.id = t1.id
You can use outer join:
SELECT DISTINCT t1.id, CASE WHEN t2.id IS NULL THEN 0 ELSE 1 END AS test
FROM t1 LEFT JOIN t2 ON t2.id = t1.id
Use exists:
select t1.*,
(case when exists (select 1 from t2 where t2.id = t1.id) then 1 else 0 end) as flag
from t1;
Note that select distinct is not needed. That construct just slows down queries, if it is not needed.
Use Left Join to get the unmatched rows as well.
select t1.id
, case when t2.id is null then 0 else 1 end as test
from t1
left outer join t2
on t1.id = t2.id

How do I get the results of one JOIN and THEN feed those into a separate join in T-SQL?

I'm trying to JOIN 2 tables ON a key like
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
Now, I have a 3rd table that has a Foreign Key with t2's id that I want to join... When I do
LEFT JOIN
Table3 t3 ON t3.t2id = --<-------------- This is where I'm lost
I don't know if I should do ON t3.t2id = t1.t2id OR ON t3.t2id = t2.id
What I need is the list of t2ids which are still in the picture after the first join. However, it seems as though if I specify either of the above, it will just pull ids from the original table before the first join?
To clarify one more time: I'm trying to essentially do a INNER JOIN of Table1 and Table2, get the resulting table, then get the t2ids of those results and feed them into a final join such that the final result contains all of Table3's rows as well as the data from the first join
You said: "final result contains all of Table3's rows as well as the data from the first join".
It means that you need
Table3 LEFT JOIN <previous results>
instead of
<previous results> LEFT JOIN Table3
The easiest way to write it is to use Common-Table Expressions:
WITH
CTE_InnerJoin
AS
(
SELECT column1, column2, t1.t2id
FROM
Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
)
SELECT
CTE_InnerJoin.column1
,CTE_InnerJoin.column2
,Table3....
FROM
Table3
LEFT JOIN CTE_InnerJoin ON CTE_InnerJoin.t2id = Table3.t2id
;
It doesn't matter what column you include in the CTE: t1.t2id or t2.id, the values in them are the same, because they are inner-joined together.
JOINs already do exactly what you want. A JOIN isn't always between two tables. Frequently, it's between the results of previous joins.
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
LEFT JOIN
Table3 t3 ON t3.t2id = t2.id
At the point at which you're writing the final ON clause here, what you're joining is precisely the results of the previous INNER JOIN on the left and the table Table3 on the right. All of t1, t2 and t3 are in scope within the ON clause, but note that t1 and t2 are now both used as aliases into the same source of rows - the previous INNER JOIN.
As a further example, consider the "diamond join":
SELECT
*
FROM
t1
left join
t2
on
t1.a = t2.b
left join
t3
on
t1.c = t3.d
inner join
t4
on
t2.e = t4.f OR
t3.g = t4.h
This is a way of joining two tables (t1 and t4) based on two alternative joins. Note that in the final inner join, what is on the "left" is the result of already joining tables t1, t2 and t3.
Join the table having foreign key with
Try this....
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
LEFT join Table3 t3 ON t2.id=t3.t2id
Or Like this.
SELECT t12.column1 ,
t12.column2 ,
t3.*
FROM (
--- INNER JOIN of Table1 and Table2, get the resulting table,
SELECT t1.column1 ,
t2.column2 ,
t1.t2id --- or t2.id doesn't matter because its inner join
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
) T12
LEFT JOIN Table3 T3 ON t3.t2id = t1.t2id --- then get the t2ids of those results
--- and feed them into a final join
--- if you want to get all rows from Table3, Change LEFT JOIN Table3 T3 ON t3.t2id = T1.t2id
--- into RIGHT JOIN Table3 T3 ON t3.t2id = T1.t2id
try this
select t3.*, column1, column2
from
table1 t1 inner join table2 t2 on t1.t2id = t2.id
right outer join table3 t3 on t3.t2id = t2.id
equvalent to
select t3.*, column1, column2
from
table1 t1 inner join table2 t2 on t1.t2id = t2.id
right outer join table3 t3 on t3.t2id = t1.t2id
if you want all rows from table 3 and those matching rows from table1 inner joined to table2 then you can use this syntax:
select t3.*,
column1, column2
from table3 t3
left join table2 t2
inner join table1 t1
on t1.t2id = t2.id
on t3.t2id = t2.id

Convert to join query

select t.* from table1 t where t.id NOT IN(
select Id from t2 where usrId in
(select usrId from t3 where sId=value));
I the result i need is like if there are matching id's in t1 and t2 then those id's should be omitted and only the remaining rows should be given to me. I tried converting into join but it is giving me the result i wanted. Below is my join query.
SELECT t.* FROM table1 t JOIN table2 t2 ON t.Id <> t2.Id
JOIN table3 t3 ON t3.Id=t2.Id WHERE t3.sId= :value
This doesn't feth me the correct result. it was returning all the rows, but i want to restrict the result based on the matching id's in table t1 and table t2. Matching id's should be ommited from the result.I will be passing the value for sId.
I believe this to be an accurate refactor of your query using joins. I don't know if we can do away with the subquery, but in any case the logic appears to be the same.
select t1.*
from table1 t1
left join
(
select t2.Id
from table2 t2
inner join table3 t3
on t2.usrId = t3.usrId
where t3.sId = <value>
) t2
on t1.Id = t2.Id
where t2.Id is null
Let's break down and solve problem step by step.
So your query
select t.* from table1 t where t.id NOT IN(
select Id from t2 where usrId in
(select usrId from t3 where sId=value));
on converting the inner query to JOIN will yield
select t.* from table1 t where t.id NOT IN
(SELECT T2.ID FROM T2 JOIN T3 on T2.UsrID =T3.UsrID and T3.sID=value)
which on further converting to JOIN with outer table will be
select t.* from table1 t LEFT JOIN
(SELECT T2.ID FROM T2 JOIN T3 on T2.UsrID =T3.UsrID and T3.sID=value)t4
ON t.id =T4.ID
WHERE t4.ID is NULL
In case you completely want to remove sub-query you can try like this
SELECT t.*
FROM table1 t
LEFT JOIN T2
ON T.ID=T2.ID
LEFT JOIN T3
ON T3.UsrId=T2.UsrID AND T3.sId=value
WHERE T3.UsrID IS NULL