I have the following query on a sql server 2008 r2:
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
/*Then it exists*/
DROP TABLE #temp
Select *
FROM
openquery(mysqlserver, 'select
id,street,name,customer,customerId
from table1 as t1
left join table2 as t2
on t2.id=t1.id
left join table3 as t3
on t3.id=t1.id
left join table4 as t4
on t4.id=t1.producto_id
left join table5 as t5
on t1.id = t5.id
where t1.type=0
and t3.service=''X''
and t1.check is null
and t1.date > date_sub(CURDATE(),INTERVAL 5 DAY)
')
SELECT * FROM #temp as t
left join View as v on v.customerId=t.customerId collate
SQL_Latin1_General_CP1_CI_AI
The above statement shows an execution plan where there is an index scan which costs 27% and another one which cost 26%. This is in related of the left join operation in one of the tables inside the view.
I thought to add index in the temp table with this:
CREATE NONCLUSTERED INDEX ix_temp_customerId on #temp(customerId)
It still the same, so I tried to apply the collate before to create the index:
ALTER TABLE #temp alter COLUMN customerId varchar(30) collate SQL_Latin1_General_CP1_CI_AI
Then the last query of the first statement was:
SELECT * FROM #temp as t
left join View as v on v.customerId=t.customerId
This shows the collation error despite the view uses this collation, and the tables inside the view query uses this collation. Then I add again the collate statement to the query.
The current statement is:
Select *
FROM
openquery(mysqlserver, 'select
id,street,name,customer,customerId
from table1 as t1
left join table2 as t2
on t2.id=t1.id
left join table3 as t3
on t3.id=t1.id
left join table4 as t4
on t4.id=t1.producto_id
left join table5 as t5
on t1.id = t5.id
where t1.type=0
and t3.service=''X''
and t1.check is null
and t1.date > date_sub(CURDATE(),INTERVAL 5 DAY)
')
ALTER TABLE #temp alter COLUMN customerId varchar(30) collate SQL_Latin1_General_CP1_CI_AI
CREATE NONCLUSTERED INDEX ix_temp_customerId on #temp(customerId)
SELECT * FROM #temp as t
left join View as v on v.customerId=t.customerId collate
SQL_Latin1_General_CP1_CI_AI
This execution plan still showing that there is an index scan. I would like to change this into index seek but I do not achieve that.
Any suggestion to achieve better performance?
Thank you
Share your execution plans using Paste The Plan # brentozar.com here are the instructions: How to Use Paste the Plan.
I would try explicitly creating your #temp table with the correct datatype, size, and collation (match the size of customerId to the varchar() size of View.customerId).
I would also consider including the columns in the index, since you are using select *.
create table #temp (
id int
, street varchar(128) collate SQL_Latin1_General_CP1_CI_AI
, name varchar(128) collate SQL_Latin1_General_CP1_CI_AI
, customer varchar(128) collate SQL_Latin1_General_CP1_CI_AI
, customerId varchar(30) collate SQL_Latin1_General_CP1_CI_AI
);
insert into #temp
select *
from openquery(mysqlserver, '
select
id,street,name,customer,customerId
from table1 as t1
left join table2 as t2
on t2.id=t1.id
left join table3 as t3
on t3.id=t1.id
left join table4 as t4
on t4.id=t1.producto_id
left join table5 as t5
on t1.id = t5.id
where t1.type=0
and t3.service=''X''
and t1.check is null
and t1.date > date_sub(CURDATE(),INTERVAL 5 DAY)
')
create nonclustered index ix_temp_customerId
on #temp(customerId)
include (id, street, name, customer);
select *
from #temp as t
left join View as v
on v.customerId=t.customerId
Related
I have two tables in MSSQL with the same structure T1 & T2. Both tables can INNER JOIN on Id but T2 may not contain the AccountId associated with the Id as in T1.
.
T1 Id AccountId Name T2 Id AccountId Name
111 5555 John 111 5555 John
122 5555 David 133 5555 Sharon
133 5555 Sharon
Below is the code I tried but the result is not working?.
.
INSERT INTO T3
SELECT T1.Id,T1.AccountId,T1.Name
FROM T1
INNER JOIN T2 T2.Id = T1.id
LEFT OUTER JOIN T1.AccountId = T2.AccountId
WHERE AccountId = 5555
The expected result would be to insert values that are not in T1 into T3
You need where clause:
INSERT INTO T3(Id, AccountId, Name)
SELECT T1.Id, T1.AccountId, T1.Name
FROM T1 LEFT JOIN
T2
ON T2.Id = T1.id
WHERE T2.AccountId IS NOT NULL;
Notes:
Only one LEFT JOIN is necessary. I don't know what the INNER JOIN is for.
Every JOIN should be followed by an ON clause.
You should list the columns when doing an INSERT.
You need the WHERE to find non-matches.
This query could also be written using NOT EXISTS.
This should be what you're after:
CREATE TABLE #T1 (id int, AccountId int, [Name] varchar(6));
CREATE TABLE #T2 (id int, AccountId int, [Name] varchar(6));
CREATE TABLE #T3 (id int, AccountId int, [Name] varchar(6));
INSERT INTO #T1
VALUES (111,5555,'John '),
(122,5555,'David '),
(133,5555,'Sharon');
INSERT INTO #T2
VALUES (111,5555,'John '),
(133,5555,'Sharon');
INSERT INTO #T3 (id, AccountId, [Name])
SELECT T1.id,
T1.AccountId,
T1.[Name]
FROM #T1 T1
LEFT JOIN #T2 T2 ON T1.ID = T2.id
WHERE T2.id IS NULL;
SELECT *
FROM #t3;
DROP TABLE #T1;
DROP TABLE #T2;
DROP TABLE #T3;
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)
Situation:
I have two tables
Table 1 always has records
Table 2 is the result of a select statement and may or may not have records
Desired Results:
If Table 2 has ANY records, I want only matching records from Table 1. Otherwise, I want all records from Table 1.
I realize I can do this:
DECLARE #count int
SELECT #count=COUNT(*) FROM Table2
IF #count>0
SELECT t1.* FROM Table1 t1 INNER JOIN Table2 t2 ON t1.id=t2.id
ELSE
SELECT * FROM Table1
However, I am trying to avoid IF statements if possible.
Is that even possible?
select t1.*
from Table1 t1
left join
Table2 t2
on t1.id = t2.id
where t2.id is not null -- Match found
or not exists -- Or Table2 is empty
(
select *
from Table2
)
I need to add the results from a Left Join query to a table that does not have its index set to be an identity, but the int must still be unique. My insert query looks like this:
INSERT INTO Table1 (S.SubjectID, S.Subject, S.SubjectDescription, S.Status)
SELECT (Select MAX(SubjectID) FROM Table1) + ???? , N.Code, N.Literal, N.Trans
FROM Table2 N LEFT JOIN Table1 S ON N.Code = S.Subject
WHERE (N.Code IS NULL OR S.Subject IS NULL OR N.Trans = 'D')
Where I have the ???? is where i need to have some incrementing value so that when inserting into the table1 the ID's will be unique.
I am not allowed to change the table's structure, I just need something that can calculate his on the fly.
As always help, tips and references are much appreciated.
In most databases, you can use row_number() for this purpose. Here is an example with SQL Server syntax:
INSERT INTO Table1 (S.SubjectID, S.Subject, S.SubjectDescription, S.Status)
SELECT (Select MAX(SubjectID) FROM Table1) + row_number() over (order by (select NULL)) ,
N.Code, N.Literal, N.Trans
FROM Table2 N LEFT JOIN Table1 S ON N.Code = S.Subject
WHERE (N.Code IS NULL OR S.Subject IS NULL OR N.Trans = 'D')
I have to select player name, Captain name from below mentioned table structure.
table structure are as follows.
create table #temp (Playerid int, PlayerName varchar (100), CaptainId int)
PlayerId PlayerName CaptainId
--------------------------------------
1 Dhoni NULL
2 Sachin 1
3 Rahul 1
I have to select player name along with his captain name from this table.
Can anybody
there are various ways to get answer of this queries like:
select playerName, (select t2.playername from #temp t2 where t2.playerid = t.captainid ) from #temp t
select t1.playername , t2.playername captain from #temp t1 left join #temp t2 on t1.captainid = t2.playerid
Assuming the CaptainId references the PlayerId on the same table, you would want the following:
select t.PlayerName, t2.PlayerName as CaptainName
from #temp t
left join #temp t2 on t.CaptainId = t2.PlayerId
If you wanted to exclude players with no captain, you would make it an inner join.
You could convert the null, of course:
select t.PlayerName, isnull(t2.PlayerName,'None') as CaptainName
from #temp t
left join #temp t2 on t.CaptainId = t2.PlayerId
You can use a self join and table aliases.
Something like
SELECT p.PlayerName,
c.PlayerName CaptainName
FROM #temp p LEFT JOIN
#temp c ON p.CaptainId = c.PlayerId
SELECT PlayerName, CaptainName
FROM PlayerTable INNER JOIN CaptainTable
ON PlayerTable.CaptainID=CaptainTable.CaptainID
WHERE CaptainName = 'your query'