Join Result Sets Mechanism - sql

Look at a simple sql code:
declare #t1 table (id int);
insert into #t1(id) values(1),(2),(3);
select * from #t1
declare #t2 table (id int);
insert into #t2(id) values(9);
select * from #t2
select * from #t1, #t2; -- q1
select ds1.id from #t1 as ds1, (select id from #t2) as ds2 -- q2
Why result of q1 and q2 is different, aren't they supposed to be same?

declare #t1 table (id int);
insert into #t1(id) values(1),(2),(3);
select * from #t1
declare #t2 table (id int);
insert into #t2(id) values(9);
select * from #t2
select * from #t1, #t2; -- q1
select ds1.id from #t1 as ds1, (select id from #t2) as ds2
In this scenario, (select id from #t2) as ds2 is considered as a derived table. You didn't fetch the column in your query.
Try this:
select ds1.id,ds2.id
from #t1 as ds1,
(select id from #t2) as ds2 -- q2
OutPut:
id id
1 9
2 9
3 9

Related

SQL server : Replace the value using like operator

I need to replace the column value if exists to another column have a same text as like below example.
create table #t1
(
a varchar(100)
)
create table #t2
(
b varchar(100),
c varchar(100)
)
insert into #t1 values('she is a girl teacher and he is a boy doctor')
insert into #t2 values('girl','G')
insert into #t2 values('boy','B')
select *from #t1
select *from #t2
select a=replace (t1.a,t2.b,t2.c)
from #t1 t1 inner join #t2 t2 on t1.a like '%'+t2.b+'%'
while i'm selecting the query the result displays like
she is a G teacher and he is a boy doctor
she is a girl teacher and he is a B doctor
but i have need the output like
she is a G teacher and he is a B doctor
How need to change my query for the above output.
The only solution I can think if using recursive queries.
create table #t1
(
a varchar(100)
)
create table #t2
(
b varchar(100),
c varchar(100)
)
insert into #t1 values('she is a girl teacher and he is a boy doctor')
, ('she is a girl soldier and he is a boy doctor')
, ('she is a girl dentist and he is a boy farmer')
insert into #t2 values('girl','G')
insert into #t2 values('boy','B')
select *from #t1
select *from #t2
select a=replace(t1.a,t2.b,t2.c), *
from #t1 t1
inner join #t2 t2 on t1.a like '%'+t2.b+'%';
with cte as (
select a, 1 as ct from #t1
union all
select cast(replace(a,t2.b,t2.c) as varchar(100)) as a, ct+1 from cte
cross apply #t2 t2 where a like '%'+t2.b+'%'
)select distinct a from (select a, ct as ct from cte) as t1 where t1.ct = (select max(ct) from cte);
drop table #t1
drop table #t2
-- she is a G teacher and he is a B doctor
The most straightforward way is to just use a cursor to loop through all the replacements, applying them.
create table #t1
(
a varchar(100)
)
create table #t2
(
b varchar(100),
c varchar(100)
)
insert into #t1 values('she is a girl teacher and he is a boy doctor')
insert into #t2 values('girl','G')
insert into #t2 values('boy','B')
-- We create a couple of variables and a temporal table to hold the incremental replacements
declare #Pattern varchar(64)
declare #Value varchar(64)
select * into #TempReplacements from #1
-- Apply the replacements
declare Replacements cursor for select b, c from #t2
open Replacements
fetch next from Replacements into #Pattern, #Value
while ##fetch_status = 0
update #TempReplacements set a = replace(a, #Pattern, #Value)
fetch next from Replacements into #Pattern, #Value
end
close Replacements
deallocate Replacements
-- We return the results
select * from #TempRelacements
-- Drop temporary Table
drop table #TempReplacements
drop table #t1
drop table #t2

Delete from memory table if in another in memory table

I have 2 in memory tables #Holding and #P1
if the row is in #P1 I want to remove it from #Holding
With my code below the duplicates are not being removed. I do not have a primary Id key like many examples, For a unique row I have Drawing, Method and Location.
DELETE h
FROM #Holding h
INNER JOIN #P1 p1 ON p1.DRAWING = h.DRAWING and p1.Method = h.Method and
p1.LOCATION = h.LOCATION
You could try using a where exists
DELETE h
FROM #Holding h
WHERE EXISTS (
SELECT *
FROM #P1 p1
WHERE p1.DRAWING = h.DRAWING and p1.Method = h.Method and p1.LOCATION = h.LOCATION
)
if your duplicates are not being removed, is because the requirement to join with #P1 to find them is incorrect.
Just to show an example that the delete/join works as expected:
declare #t1 table (c1 int)
declare #t2 table (c1 int)
insert into #t1 values (1),(2),(3)
insert into #t2 values (1)
delete #t1
from #t1 t1
join #t2 t2
on t1.c1=t2.c1
select * from #t1

Insert to table based on another table if doesn’t exist

From doing a bit of research it seems it’s not possible to do an insert with a where clause?
I have a table I want to import into another table where specific record criteria doesn’t already exist. How would I go about this ?
E.g pseudo code -
insert into table b (select * from table a) where not exists tableb.column1 = tablea.column1 and tableb.column2 = tablea.column2
Could this potentially be done with a Join ?
You can insert using INSERT INTO.. SELECT with NOT EXISTS.
Query
insert into [TableB]
select * from [TableA] as [t1] -- [TableA] and [TableB] structure should be same.
where not exists(
select 1 from [TableB] as [t2]
where [t1].[column1] = [t2].[column1]
and [t1].[column2] = [t2].[column2]
);
Or, if the table structure is not same and need to same few columns, then
Query
insert into [TableB]([column1], [column2], ..., [columnN])
select [column1], [column2], ..., [columnN]
from [TableA] as [t1]
where not exists(
select 1 from [TableB] as [t2]
where [t1].[column1] = [t2].[column1]
and [t1].[column2] = [t2].[column2]
);
You can also use LEFT JOIN with IS NULL as below:
INSERT INTO tableb
SELECT a.*
FROM tablea a
LEFT JOIN tableb b ON b.column1 = a.column1
AND b.column2 = a.column2
WHERE b.column1 IS NULL
Referencing table name from INSERT statement in SELECT part will not work, because INSERT is not a query itself, but nothing prevents to query destination table in SELECT, which produces the data set to be inserted.
INSERT INTO tableb (column1, column2)
SELECT column1, column2 FROM tablea
WHERE NOT EXISTS (SELECT * FROM tableb
WHERE tableb.column1 = tablea.column1
AND tabled.column2 = tablea.column2)
Try this :
Via Insert with Select statement with Not Exists
Declare #table1 table(Id int , EmpName varchar(100) )
Declare #table2 table(Id int , EmpName varchar(100) )
Insert into #table1 values (1,'Ajay'), (2, 'Tarak') , (3,'Nirav')
Insert into #table2 values (1,'Ajay')
--Insert into table b (select * from table a) where not exists tableb.column1 = tablea.column1 and tabled.column2 = tablea.column2
INSERT INTO #table2 (id, empname)
select id, empname from #table1
EXCEPT
SELECT id, empname from #table2
Select * from #table1
Select * from #table2
Via merge
Insert into #table2 values (4,'Prakash')
Select * from #table1
Select * from #table2
Declare #Id int , #EmpName varchar(100)
;with data as (select #id as id, #empname as empname from #table1)
merge #table2 t
using data s
on s.id = t.id
and s.empname = t.empname
when not matched by target
then insert (id, empname) values (s.id, s.empname);
Select * from #table1
Select * from #table2

Select one records from three tables based on latest date

I have a TransactionMaster table in SQL Server 2012 that has unique TransactionID. The same TransactionID wil be availabe in LowTransaction ,MediumTransaction and HighTransaction tables.
For each TransactionID in TransactionMaster, I need to display one StatusMessage. The StatusMessage may come from any of the 3 tables - based on date formulated from CRTDTEC and CRTTIME columns..
What is the best way in SQL Server 2012 to select the StatusMessage corresponding to latest date?
Note: CRTDTEC Format - YYMMDD and CRTTIME Format - HHMMSS
CODE
DECLARE #TransactionMaster TABLE (TransactionID INT)
DECLARE #LowTransaction TABLE (TransactionID INT, StatusMessage VARCHAR(80), CRTDTEC VARCHAR(8), CRTTIME VARCHAR(6))
DECLARE #MediumTransaction TABLE (TransactionID INT, StatusMessage VARCHAR(80), CRTDTEC VARCHAR(8), CRTTIME VARCHAR(6))
DECLARE #HighTransaction TABLE (TransactionID INT, StatusMessage VARCHAR(80), CRTDTEC VARCHAR(8), CRTTIME VARCHAR(6))
INSERT INTO #TransactionMaster VALUES (1)
INSERT INTO #TransactionMaster VALUES (2)
INSERT INTO #TransactionMaster VALUES (3)
INSERT INTO #LowTransaction VALUES (1,'1 Low','20131213','235959')
INSERT INTO #MediumTransaction VALUES (1,'1','20131213','235900')
INSERT INTO #HighTransaction VALUES (1,'1 High','20111213','235959')
INSERT INTO #LowTransaction VALUES (2,'2 Low','20111213','235959')
INSERT INTO #LowTransaction VALUES (3,'3 Low','20111213','235959')
INSERT INTO #MediumTransaction VALUES (3,'3 Medium','20111213','235959')
INSERT INTO #HighTransaction VALUES (3,'3 High','20140101','235959')
Expected Result
(1,'1 Low','20131213','235959')
(2,'2 Low','20111213','235959')
(3,'3 High','20140101','235959')
The simplest way would probably be
WITH TransConsolidated
AS (SELECT *
FROM #LowTransaction
UNION ALL
SELECT *
FROM #MediumTransaction
UNION ALL
SELECT *
FROM #HighTransaction)
SELECT TM.TransactionID,
CA.*
FROM #TransactionMaster TM
CROSS APPLY (SELECT TOP 1 *
FROM TransConsolidated TC
WHERE TC.TransactionID = TM.TransactionID
ORDER BY CRTDTEC DESC,
CRTTIME DESC) CA
Or another possibility (if there is a covering index ordered by TransactionID on all tables) would be to merge join all four tables involved
;WITH CTE
AS (SELECT TM.TransactionID,
MAX(CA.CRTDTEC + CA.CRTTIME + CA.StatusMessage) AS MaxRow
FROM #TransactionMaster TM
LEFT MERGE JOIN #LowTransaction LT
ON LT.TransactionID = TM.TransactionID
LEFT MERGE JOIN #MediumTransaction MT
ON MT.TransactionID = TM.TransactionID
LEFT MERGE JOIN #HighTransaction HT
ON HT.TransactionID = TM.TransactionID
CROSS APPLY (SELECT LT.*
UNION ALL
SELECT MT.*
UNION ALL
SELECT HT.*) CA
GROUP BY TM.TransactionID)
SELECT TransactionID,
SUBSTRING(MaxRow, 1, 8),
SUBSTRING(MaxRow, 9, 6),
SUBSTRING(MaxRow, 16, 80)
FROM CTE
I guess you could do something like this...
SELECT TransactionID, StatusMessage, CRTDTEC, CRTTIME
FROM
(
SELECT *, rn = ROW_NUMBER() OVER (PARTITION BY TransactionID ORDER BY CRTDTEC DESC)
FROM
(
SELECT * FROM #LowTransaction
UNION ALL
SELECT * FROM #MediumTransaction
UNION ALL
SELECT * FROM #HighTransaction
)q
) q2
WHERE rn = 1
Result Set
TransactionID StatusMessage CRTDTEC CRTTIME
1 1 Low 20131213 235959
2 2 Low 20111213 235959
3 3 High 20140101 235959

SQL intersect with other tables, how do I ignore it?

I am trying to run a query given three tables.
DECLARE #TABLE1 TABLE (ID CHAR(2))
DECLARE #TABLE2 TABLE (ID CHAR(2))
DECLARE #TABLE3 TABLE (ID CHAR(2))
INSERT INTO #TABLE1 VALUES('1')
INSERT INTO #TABLE1 VALUES('2')
INSERT INTO #TABLE2 VALUES('1')
--NOTHING in TABLE3
I Need to get only the values that are present and ignore the null table. This doesn't work since TABLE3 has no values.
SELECT ID
FROM #TABLE1
INTERSECT
SELECT ID
FROM #TABLE2
INTERSECT
SELECT ID
FROM #TABLE3
**Result should be 1**
How do I ignore the any table if it's null but keep the other values?
Why not do a union of select distincts from each table, and then group that by ID and select count(*), and select only rows with count(*) equal to the maximum value of count(*) in the result?
It's a bit of a mess of subqueries at this point unfortunately but you should get the logic :)
Intersect is not going to work for you as you can't add conditions to it.
From what I understand you want to select all records where the ID appears in at least 2 of the tables. I am assuming that the ID is unique to each table.
The following works in MS SQL Server:
DECLARE #TABLE1 TABLE (ID CHAR(2))
DECLARE #TABLE2 TABLE (ID CHAR(2))
DECLARE #TABLE3 TABLE (ID CHAR(2))
INSERT INTO #TABLE1 VALUES('1')
INSERT INTO #TABLE1 VALUES('2')
INSERT INTO #TABLE2 VALUES('1')
--NOTHING in TABLE3
;WITH AllValues AS
(
SELECT ID
FROM #TABLE1
UNION ALL
SELECT ID
FROM #TABLE2
UNION ALL
SELECT ID
FROM #TABLE3
)
SELECT ID
FROM AllValues
GROUP BY ID
HAVING COUNT(*) > 1
Maybe... But the design of the system is extremely foreign; a real world example would help understand what you're trying to do.
Select count(*), ID FROM (
Select ID from #table1
UNION
Select ID from #table2
UNION
Select ID from #table3) Derived
Where RowNum =1
GROUP BY ID
ORder by count(*) DESC
Updated where clause was in wrong place