I have the below query
select *
from monthly_accounts m
join blocks_Dep on (m.code = d.code )
where exists (select R_code
from balance c
inner join blocks_div d on (m.b_id = d.b_id and c.name = d.name)
)
I am getting an error about an invalid m.b_i identifier; how to make join between the first table and tables in exists with the join?
Maybe you are getting that error because the operator is exists not exist. Does this work?
select m.*, d.*
from monthly_accounts m join
blocks_Dep d
on m.code = d.code
where exists (select 1
from balance b inner join
blocks_div bd
on b.name = bd.name
where m.b_id = bd.b_id
);
Note that I made other changes and fixed other problems:
blocks_dep did not have a table alias.
I assigned table aliases that are abbreviations of the table names for all tables.
I moved the correlation clause to a where rather than the on. I don't expect to see correlation clauses in an on (although the logic is correct).
You have some answers
The core should stand on it's own
Use alias and don't repeat the alias
select * from
monthly_accounts m
join blocks_Dep on (m.code=d.code)
d is not yet defined. Even the query parser figured it out I doubt that is what you wanted.
This links the not exists by m.b_id which is what I think you mean to do?
select *
from monthly_accounts m
join blocks_Dep d1
on m.code = d1.code
where not exists ( select 1
from balance c
join blocks_div d2
on d2.b_id = m.b_id
and d2.name = c.name
)
Related
I am trying to replace not in query with not exist, However it is not giving the correct count.
Current Query
Select count(*)
from employee where
employee.city not in(
Select distinct d.city from
department d, allocation a
where d.id = a.id)
The count it is giving is 348988
Now I need to replace it with exist or left join
Select count(*)
from employee where not exists
(Select 1
from
department d, allocation a
where d.id = a.id and d.city = employee.city);
The count is 410991.. Even doing the left join is giving me the same number.
Please note: we need to replace "not in" Since there is more join after "not in" and snowflake is throwing error - snowflake unsupported subquery type cannot be evaluated. which can be resolved by using not exists
Select count(*)
from employee where
employee.city not in(
Select distinct d.city from
department d, allocation a
where d.id = a.id)
a NOT IN, is the same LEFT JOIN x WHERE x.y IS NUL
Select count(*)
from employee as e
left join (
Select distinct d.city
from department as d
join allocation as a
on d.id = a.id
) as b
on b.city = e.city
where b.city is null
and in fact the DISTINCT can be expensive, and ignored as we are take the join fail thus it should be faster to:
Select count(*)
from employee as e
left join (
Select d.city
from department as d
join allocation as a
on d.id = a.id
) as b
on b.city = e.city
where b.city is null
As suggested by Dean heather it has something to do with NULL variable.
below is the modified query with not exist where the count matches with NOT IN
Select count(*)
from employee where not exists
(Select 1
from
department d, allocation a
where d.id = a.id and d.city = employee.city)
and employee.city is not NULL;
So basically I had to eliminate all the NULL city from primary table .
Although the count is perfectly matching I am now curious if NOT IN was doing the correct job.
i have a inner join query in stored procedure which is working fine. i need to inject a aggregate query in it so that it show an aggregated result in a new column
https://drive.google.com/file/d/1tAIEACvEnG7sAisSoE2crYRrzCjIcvST/view?usp=sharing
i tried to inject aggregate query as a column TotalQty in my query
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName, dbo.SOD.SalePrice
,TotalQty = (select SUM(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
But it says
Column 'dbo.SO.Id' is invalid in the select list because it is not
contained in either an aggregate function or the GROUP BY clause.
or any other good Technique suggested will be appreciated.
so change AS :
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName, dbo.SOD.SalePrice
,(select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B') AS TotalQty
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
As in the internal query, your characteristic is you used the o.SOId field on where and in other hand used count aggregate function so you should:
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName,
dbo.SOD.SalePrice
,count(dbo.SOD.Quantity) AS TotalQty
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
group by
dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name , dbo.SOD.SalePrice
Which will have the same output.
Generally speaking, you encourage others to help if you provide a MVCE. Using cryptic table names (are they tables? or views perhaps?) is not a healthy practice. In addition, it is not clear what you are trying to achieve with your subquery. You attempted to use count but you label the value as "TotalQty" and you replied to a suggestion using "sum". Very confusing.
So since we don't have your tables, I used the common MS sample database AdventureWorks. Below are two examples of counting the quantity values from the detail table.
select Ord.SalesOrderID, Det.SalesOrderDetailID,
Cust.AccountNumber as CustName, -- too lazy to get actual name
Prd.Name as ProductName,
Det.UnitPrice
,Counted.TotalQty
-- TotalQty = (select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
from Sales.SalesOrderHeader as Ord
inner join Sales.SalesOrderDetail as Det on Ord.SalesOrderID = Det.SalesOrderID
inner join Production.Product as Prd on Det.ProductID = Prd.ProductID
inner join Sales.Customer as Cust on Ord.CustomerID = Cust.CustomerID
cross apply (select count(DetCnt.OrderQty) as TotalQty from Sales.SalesOrderDetail as DetCnt where DetCnt.SalesOrderID = Det.SalesOrderID) as Counted
where Ord.SalesOrderID = 43659
select Ord.SalesOrderID, Det.SalesOrderDetailID,
Cust.AccountNumber as CustName, -- too lazy to get actual name
Prd.Name as ProductName,
Det.UnitPrice
, TotalQty = (select count(DetCnt.OrderQty) from Sales.SalesOrderDetail as DetCnt where DetCnt.SalesOrderID = Det.SalesOrderID)
-- TotalQty = (select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
from Sales.SalesOrderHeader as Ord
inner join Sales.SalesOrderDetail as Det on Ord.SalesOrderID = Det.SalesOrderID
inner join Production.Product as Prd on Det.ProductID = Prd.ProductID
inner join Sales.Customer as Cust on Ord.CustomerID = Cust.CustomerID
where Ord.SalesOrderID = 43659
I think that interpretation is correct but I don't know your schema. I added the PK of the detail table to help "see" the relationship between Order and Detail.
Examine the code closely. Notice how the query only refers to the specific PK value once (this would be your procedure's parameter). You use correlations and joins to limit the results as needed. And notice how much easier it is to understand the query since it uses names that are actual words - SalesOrder vs. SO. I don't think it makes much sense to right join your Detail table to the Order table - seems like a mistake. Your aggregation attempt is odd so I can't say if the value computed by these queries is correct.
I'll also note that you should not be passing the PK value of your table using a nvarchar parameter. Use the correct datatype to avoid the possibility that someone attempts to pass an actual string (e.g., N'Pick me') instead of a GUID value.
I have three joins in my query. My requirement is to select records if either first two joins get satisfied or the third join gets satisfied
select * from security.requestview r
-- either below two joins satisfy
left join security.RequestDelegateView rd on r.id = rd.RequestId
join (select top 1 PersonnelNumber from SECURITY.MyRolesView) m on (m.PersonnelNumber=r.RequestorId or m.PersonnelNumber=r.InitiatorId or m.PersonnelNumber=rd.DelegatePersonnelNumber)
-- or this join
join (select substring(ltrim(DDSUCode),0,3) as Division from security.staffview where PersonnelNumber = (select top 1 PersonnelNumber from SECURITY.MyRolesView)) s
on r.OrganizationUnitRefId like s.Division+'%'
But ofcourse it will try to satisfy all the joins together.
Is there any way I can put some condition where it will select record if either first two joins satisfy or the last join alone satisfies?
Update
I tried putting them as where conditions but then the query is running forever
To answer this question:
Is there any way I can put some condition where it will select record
if either first two joins satisfy or the last join alone satisfies?
No, I know of no way to do this in a single query.
One way you can write this so that the third join only gets executed if the first one doesn't return records is in a multi-query series that populates a temp table or table variable:
INSERT INTO #tmp
SELECT (the first join);
IF (SELECT COUNT(*) FROM #tmp) = 0
INSERT INTO #tmp
SELECT (the second join);
SELECT * FROM #tmp;
WITH FirstJoin AS (
select * from security.requestview r
left join security.RequestDelegateView rd on r.id = rd.RequestId
join (select top 1 PersonnelNumber from SECURITY.MyRolesView) m on (m.PersonnelNumber=r.RequestorId or m.PersonnelNumber=r.InitiatorId or m.PersonnelNumber=rd.DelegatePersonnelNumber)
), SecondJoin AS (
select * from security.requestview r
join (select substring(ltrim(DDSUCode),0,3) as Division from security.staffview where PersonnelNumber = (select top 1 PersonnelNumber from SECURITY.MyRolesView)) s
on r.OrganizationUnitRefId like s.Division+'%'
), BothJoins AS (
SELECT * FROM FirstJoin
UNION ALL
SELECT * FROM SecondJoin
)
SELECT DISTINCT * FROM BothJoins
To get this to work you need to Change the "Select *" inside the CTE's so that every returned column is named. (Since I don't know whats in your tables I couldn't do it).
Please note that FirstJoin and SecondJoin needs to return the same columns.
select *
from table1
left join table2
on table1.id = table2.t1
left join table3
on table1.id = table3.t1
left join table4
on table1.id = table4.t1
where table2.t1 is not null
or table3.t1 is not null
or table4.t1 is not null
I am trying to rewrite legacy join syntax with new standards.
SELECT count(*)
FROM es_dbo.tablTypes t
,es_dbo.tablReg r
,es_dbo.tabl_PRGandCLI p
WHERE t.ClientType *= r.ClientType
AND p.ID IN (
SELECT DISTINCT ClientID
FROM esinet_dbo.tablReG
)
AND t.ClientType IN (#intClientType)
Here is what I am trying.
SELECT count(*)
FROM es_dbo.tablTypes t
LEFT JOIN es_dbo.tablReg r ON t.ClientType = r.ClientType
LEFT JOIN es_dbo.tabl_PRGandCLI p ON p.ID IN (
SELECT DISTINCT ClientID
FROM es_dbo.tablReG
)
I am getting same no of records whether I use LEFT JOIN or INNER JOIN in 2nd part of query. Can anyone explain
Try the following:
SELECT count(*)
FROM es_dbo.tablTypes t
left join es_dbo.tablReg r on t.ClientType = r.ClientType
WHERE t.ClientType IN (#intClientType)
EXISTS (SELECT 1 FROM esinet_dbo.tablReG p WHERE r.ClientID = p.ID)
1) I assumed #intClientType is a scalar value, so no need for IN
2) removed DISTINCT and subquery as you check for existence. EXISTS should be faster as it involves finding the first element, rather than doing some sorting for DISTINCT.
3) *= was replaced with LEFT JOIN, based on discussion from here.
It is neither inner join nor left join according to query it seems like cross join so you can use following query:
SELECT count(*)
FROM es_dbo.tablTypes t
LEFT JOIN es_dbo.tablReg r ON t.ClientType = r.ClientType,
es_dbo.tabl_PRGandCLI p WHERE p.ID IN (
SELECT DISTINCT ClientID
FROM es_dbo.tablReG
)
I have two tables and did an inner join on them based on id. Now I need to name this joined table. How do I do that? The reason I want to name this table is because I have to join this result table with some other tables.
You created what is commonly referred t as a relvar, not another table. You can join to it by placing it's SELECT definition in a sub query like this:
SELECT
FROM (
-- original join SQL
) t
INNER JOIN table2 on ...
You can create an alias for the result of a join using a subquery. For example:
select *
from (
select *
from tbl1
join tbl2
on tbl1.id = tbl2.id
) as JoinAlias
join tbl3
on JoinAlias.id = tbl3.id
You can often make do without such an alias. For example, consider a third join:
select *
from tbl1
join tbl2
on tbl1.id = tbl2.id
join tbl3
on tbl3.col1 = tbl1.col1
and tbl3.col2 = tbl2.col2
As you can see, the third join's condition can refer to columns from all earlier tables.
select * from (
select * from TableA a join TableB b on a.id = b.a_id
) as p;
As per the comments, it seems that a view might be what you are looking for:
create view MyView
as
select * from TableA a join TableB b on a.id = b.a_id;
It won't be listed in the tables (rather in the views), but will behave just like a table in your sql editor.