SQL Server : Left Join using 1 = 1 - sql-server

My application is developed using framework so I need to follow some structure which can't be changed.
In SQL Server, I need to achieve inner join using left join which is possible using 1=1
Now in my case there is an Account table with few details, and account_ext table with a few more columns of account related information.
There is an ACCT_NAME_LNK table which has link to particular name to particular account and it has expiry date also
Now I need to fetch all records which has link to name link table and acct table
My conditions is it should not show expired records and in or condition T2.AcctHDDescription like '6%'
This means there should be link to name or ACCTHDDescription should like '6%'
So it should not show expired record but it is showing
Below is my query
DECLARE #EXPDATE DATETIME
SET #EXPDATE = GETDATE()
SELECT DISTINCT
T1.ID, T1.AccountID, T2.AcctHDDescription
FROM
ACCT T1
LEFT JOIN
ACCT_Ext T2 ON T1.ID = T2.ID
LEFT JOIN
ACCT_NAME_LNK T3 ON 1 = 1
AND ISNULL(T3.EXPIRED, '2999-12-31') > #EXPDATE
WHERE
T1.ID = T3.acctid OR T2.AcctHDDescription LIKE '6%'
Added one more image with more details
I need to achieve the output using left join on 1=1
And it has Or condition
[{Link available and not expired} or {AcctHDDescription = '6%'}]
Latest Image which shows output
Expected output
Id AccountId AcctHDDDescription
3 33333 1234
4 62343 345
6 624323 6667

That is a bit of a strange query but I think your issue lies in the WHERE clause OR condition. My initial guess is you want to move the ID join into the left join:
declare #EXPDATE datetime
set #EXPDATE=GETDATE()
SELECT DISTINCT T1.ID,T1.AccountID ,T2.AcctHDDescription
FROM ACCT T1 LEFT JOIN ACCT_Ext T2 ON T1.ID = T2.ID
LEFT JOIN ACCT_NAME_LNK T3 ON 1 = 1
AND ISNULL( T3.EXPIRED, '2999-12-31' ) > #EXPDATE
AND T1.ID = T3.acctid
where T2.AcctHDDescription like '6%'

Just guessing what you want,
DECLARE #EXPDATE DATETIME
SET #EXPDATE=GETDATE();
SELECT T1.ID
, T1.AccountID
, T2.AcctHDDescription
, T3.Expired
FROM Acct T1
LEFT JOIN Acct_Ext T2
ON T1.ID = T2.ID
LEFT JOIN ACCT_NAME_LNK T3
ON T1.ID = T3.acctid
WHERE (T2.AcctHDDescription like '6%' AND ISNULL(T3.EXPIRED, '2999-12-31' ) > #EXPDATE)
OR ISNULL( T3.EXPIRED, '2999-12-31' ) > #EXPDATE;

Related

Invalid t1.id in select list because it is not contained in either an aggregate function or group by clause

I have two table t1 and t2,
Where t1 has the data like:
Id. Name
1. Ab
2. Dc
3. Cd
t2 has the data as given:
Id. Revenue
1. 100
2. 0
3. 200
And my SQL query is:
select t1.id ,t1.name,sum(t2.rev)
from t1
inner join t2 on t1.id= t2.id
where t1.id=100 and t2.Revenue <> 0
group by t1.id
Just put to GROUP BY columns that you want to select:
select t1.id ,t1.name,sum(t2.rev)
from t1
inner join t2 on t1.id= t2.id
where t1.id=100 and t2.Revenue <> 0
group by t1.id, t1.name, t2.rev
The error means that that you've got SUM of t2.rev field - one row, but SQL Server has also many rows with calculated column and it does not know what a row exactly should be chosen.
UPDATE:
If one of your some column has type such as text, ntext or image, then you should cast it to NVARCHAR type:
select t1.id ,t1.name,sum(t2.rev)
from t1
inner join t2 on t1.id= t2.id
where t1.id=100 and t2.Revenue <> 0
group by t1.id, CAST( t1.name AS NVARCHAR(100)), CAST( t2.rev AS NVARCHAR(100))
UPDATE 1:
TEXT, NTEXT and IMAGE are old type of variable and there types are deprecated. So these types be replaced or casted by the corresponding types VARCHAR(MAX), NVARCHAR(MAX) and VARBINARY(MAX).
If you have just one column of type of TEXT, then just CAST just this column:
select t1.id ,t1.name,sum(t2.rev)
from t1
inner join t2 on t1.id= t2.id
where t1.id=100 and t2.Revenue <> 0
group by t1.id, CAST( t1.name AS NVARCHAR(100)), t2.rev
If anything, the column causing the error would be t1.name1 Since the name is completely dependent on the ID, you can artificially add it to the group by clause without harming the query's correctness:
select t1.id ,t1.name,sum(t2.rev)
from t1
inner join t2 on t1.id= t2.id
where t1.id=100 and t2.Revenue <> 0
group by t1.id, t1.name
if you want to display any column and you used group by than you must group by one those column also
select t1.id ,t1.name,sum(t2.Revenue) from t1
inner join t2 on t1.id= t2.id where t1.id=1 and t2.Revenue <> 0 group by t1.id,t1.Name

insert records except in sql server

I have two tables t1 and t2.
t1 having 10k records and t2 having 2k records. The 2k records of t2 is present in t1.
I wanted the 8k different records from t1 which is not present in t2.
I'm doing this as below:
select id, second_telphon from t1
except
select id, second_telphon from t2
However, I'm still getting all the 10k records. Is "except" keyword not working?
how can I achieve this?
you can perform a Join to get the unique data from the tables .
like the tables t1 & t2 both you cna perform left or right join .
example:
SELECT T1.*
FROM T1
WHERE NOT EXISTS(SELECT NULL
FROM T2
WHERE T1.ID = T2.ID
AND T1.Date = T2.Date
AND T1.Hour = T2.Hour)
OR .
SELECT T1.*
FROM T1
LEFT JOIN T2
ON T1.ID = T2.ID
AND T1.Date = T2.Date
AND T1.Hour = T2.Hour
WHERE T2.ID IS NULL
Try this:
SELECT *
FROM T1
WHERE NOT EXISTS(SELECT id,second_telphon FROM t2)
If ID is a unique value, Try this also:
SELECT *
FROM T1
WHERE ID NOT IN(SELECT ID FROM t2)
You could try a union, followed by an aggregation to restrict to those records in the first table which were not duplicated by the second table:
SELECT id, second_telphon
FROM
(
SELECT id, second_telphon FROM t1
UNION ALL
SELECT id, second_telphon FROM t2
) t
GROUP BY id, second_telphon
HAVING COUNT(*) = 1;
If a record, being defined as an id, second_telphon pair, has a record count of only one after the union, it implies that this record was unique to the first table.
Just do left join
select t1.id,t1.second_telphon from t1
left join t2 on
t1.id = t2.id
and t1.second_telphon =t2.second_telphon
where t2.id is null

sql server left join with filter - sql server 2012

I have 2 tables . One of employees and other breaks. I want to show all records from the Employees table ( LEFT JOIN) and see if any employee rests next Sunday (if have a record in the other table - breaks
SELECT T1.idEmp
, T1.fname
, T1.lname
, T1.number
, T2.idGuard
, T2.date
FROM
tblEmp AS T1 LEFT JOIN tblEmpGuard AS T2
ON
T1.idEmp = T2.idEmp
WHERE
date = #date
this just shows me employees having break next Sunday , but not the others.
Try
SELECT T1.idEmp
, T1.fname
, T1.lname
, T1.number
, T2.idGuard
, T2.[date]
FROM tblEmp AS T1
LEFT JOIN tblEmpGuard AS T2
ON T1.idEmp = T2.idEmp
AND T2.[date] = #date
This is because the where clause is filtering for employees with a break on that date. This occurs after the join thus excluding employees without dates. Moving this criteria to the on clause will solve the problem.
SELECT T1.idEmp, T1.fname, T1.lname, T1.number, T2.idGuard, T2.date
FROM tblEmp AS T1
LEFT JOIN tblEmpGuard AS T2
ON T1.idEmp = T2.idEmp
AND T2.date = #date

SQL Server stored procedure select, exists, multiple tables

Any method to do this?
Table1
1
2
3
4
5
Table2
3 (with the condition)
4 (without the condition)
I want to:
Select all records from Table1 if it exists in Table 2, where...(condition)
Select all records from Table1 if it not exists in Table2
Combine both select results. Sort all results with their created date.
For example, the result should be:
Result
1
2
3
5
Hopefully this can help.
SELECT t1.* from table1 t1
JOIN table2 t2
ON t1.ID = t2.ID
UNION ALL
SELECT t1.* from table1 t1 where ID in
(
SELECT t2.ID from table1 t1 except Select t2.ID from table2 t2
)
ORDER BY t1.CreatedDate
You can achieve this by doing:
SELECT t1.id
FROM Table1 t1
LEFT JOIN Table2 t2 on t1.id = t2.id
WHERE condition OR t2.id IS NULL
ORDER BY t1.CreatedDate;
See fiddle (I assumed condition to be t2.id!=4, but it can be anything else depending on other data in your tables).
There could be multiple solution.
One way
we can get the result set using two different queries and at last combine both of the result-set using UNION
Another way,
First statement is saying that get all the result set from TABLE1 if it exists in TABLE2 as well with some criteria (condition in where clause)
means using INNER JOIN we can achieve this
Second statement is saying get all the result set from TABLE1 which are not present in TABLE2
means along with INNER JOIN ed query also include the TABLE1's data if not present in TABLE2
here we can take the help of LEFT OUTER JOIN (taking TABLE1 on the left side)
Assumption: (condition: t1.Id != 4)
Let's try to understand the query using both of the above mentioned ways
---- -- --Step1 Create table and insert records
---- create table1 with Id int identity columsn
--CREATE TABLE Table1 (Id INT IDENTITY(1,1), CreatedDate smalldatetime default(getdate()));
--go
---- insert 1st 5 integers into Table1
--INSERT INTO Table1 DEFAULT VALUES
--go 5
---- create Table2 with Id int column
--CREATE TABLE Table2 (Id INT , CreatedDate smalldatetime default(getdate()));
--go
---- insert records 3,5 into Table2
--INSERT INTO Table2(Id) VALUES (3), (4);
-- -- -- Solution: one way
; WITH cteMyFirstResult AS
(
-- 2.1. Select all records from Table1 if it exists in Table 2, where...(condition)
SELECT
Id, CreatedDate
FROM Table1 AS t1
WHERE t1.Id IN (SELECT Id FROM Table2 AS t2)
AND t1.Id != 4 -- assumption it can be any condition
),cteMySecondResult AS (
-- 2.2. Select all records from Table1 if it not exists in Table2
SELECT
Id, CreatedDate
FROM Table1 AS t1 WHERE t1.Id NOT IN (SELECT Id FROM Table2 AS t2)
)
-- 2.3. Combine both select results. Sort all results with their created date.
SELECT
Id, CreatedDate
FROM cteMyFirstResult
UNION
SELECT
Id, CreatedDate
FROM cteMySecondResult
ORDER BY CreatedDate;
-- -- Solution: Another way (with bug)
SELECT t1.Id, t1.CreatedDate
FROM Table1 AS t1
LEFT JOIN Table2 AS t2 on t1.id = t2.id
WHERE t1.Id != 4
Order by T1.CreatedDate;
-- in this query we are using the criteria after doing the join operation.
-- thus after filtering out the result set based on JOIN Condition this condition will get applied
-- and if there is any null record in the Table1 for column Id (used in join) will not come in the final result-set
-- to avoid this we can include NULL check along with our criteria
-- -- Solution: Another way
SELECT t1.Id, t1.CreatedDate
FROM Table1 AS t1
LEFT JOIN Table2 AS t2 on t1.id = t2.id
WHERE ( t1.Id != 4 ) OR t1.Id IS NULL -- include all your criteria within small-barcket)
Order by T1.CreatedDate;
Thanks for all responses.
I come out with the answer I want:
SELECT *
FROM Table1 t1
WHERE NOT EXISTS(SELECT 1 FROM Table2 t2
WHERE t1.ID = t2.ID
AND t2.CIF_KEY = #CifKey
AND t2.STATUS <> ''3'')
AND (condition in where clause)

Odd LEFT JOIN error

I have two tables I am trying to join together on a particular column (shared between the two). The data in these columns are supposed to represent numbers, but the data are actually characters, and some of the values are non-numeric (e.g. '2,3,4', or 'n/a'). I am ignoring the rows with non-numeric values of this column. I am treating the columns as numeric in the join because '001' must match '1', '01', '0001', etc. Inner joining them works, left outer joining them doesn't:
SELECT *
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.ID NOT LIKE '%[^ 0-9]%'
AND T2.ID NOT LIKE '%[^ 0-9]%'
AND T1.ID + 0 = T2.ID + 0
-- Success!
SELECT *
FROM Table1 T1
LEFT JOIN Table2 T2
ON T1.ID NOT LIKE '%[^ 0-9]%'
AND T2.ID NOT LIKE '%[^ 0-9]%'
AND T1.ID + 0 = T2.ID + 0
-- Conversion failed when converting the nvarchar value '2,3,4' to data type int.
Why am I getting an error on the outer join but not the inner join?
P.S.: Fixing the data is not an option. It is not my data; I cannot touch it. I have to find a way to work with it.
EDIT: I am running SQL Server 2008 R2 RTM
SQL Server does not guarantee the order in which the conditions will be evaluated. In your case, T1.ID + 0 = T2.ID + 0 is being evaluated before the NOT LIKE conditions.
Please try the following (SQL 2012 and above):
SELECT *
FROM Table1 T1
LEFT JOIN Table2 T2
ON TRY_CAST(T1.ID AS int) = TRY_CAST(T2.ID AS int)
SQL 2008:
SELECT *
FROM (SELECT * FROM Table1 WHERE ID NOT LIKE '%[^ 0-9]%') T1
LEFT JOIN (SELECT * FROM Table2 WHERE ID NOT LIKE '%[^ 0-9]%') T2
ON CAST(T1.ID AS INT) = CAST(T2.ID AS INT)
Reference
TRY_CAST (T-SQL)
what if you try this instead? does it do what you want?
SELECT *
FROM Table1 T1
LEFT JOIN Table2 T2
ON (isnumeric(T1.ID) = 1
AND isnumeric(T2.ID) = 1)
AND try_parse(T1.ID as int) + 0 = try_parse(T2.ID as int) + 0

Resources