Sorry if I am not explaining my issue the best, but basically I have two tables.
Table A has a reference column to table B. On table B there is column X where for each referenced row, there is an unreferenced row with that same value of column X (table B has double the rows of table A). I want to update the reference on table A to be the row of table B that is not currently referenced of the two rows that have the same value on column X.
In pseudo code...
update tableA
set refCol = (select tableB.refCol
from tableB
where colX = (select colX
from tableB
where tableB.refCol = tableA.refCol)
and tableB.refCol != tableA.refCol)
The innermost query returns two rows, the outer query returns one row
sample tables:
Table A
refCol
1
3
Table B
refCol
colX
1
hello
2
hello
3
hi
4
hi
expected output:
Table A
refCol
2
4
Any help would be much appreciated.
Refer it below working example
create table #tableA(
id int)
create table #tableB(
id int,
name varchar(10)
)
insert into #tableA values(1)
insert into #tableA values(3)
insert into #tableA values(5)
insert into #tableA values(6)
insert into #tableA values(7)
insert into #tableA values(8)
insert into #tableB values (1,'A')
insert into #tableB values (2,'A')
insert into #tableB values (3,'C')
insert into #tableB values (4,'C')
select * from #tableA
select * from #tableB
update aa set aa.id=ab.id from #tableA aa inner join (
select b.id,b.name,a.id as ta from (
select B.* from #tableB b left join #tableA a on a.id=b.id where a.id is null)b
inner join (
select b.* from #tableA a inner join #tableB b on a.id=b.id)a on a.name=b.name)ab on aa.id=ab.ta
I have a single column
Value
A
B
C
NULL
NULL
F
R
D
NULL
T
R
NULL
Expected Output:
value
ABC
FRD
TR
Aim is to group column values until next NULL and so on..
CREATE TABLE DUMMY1(VALUE VARCHAR(50))
INSERT INTO DUMMY1(VALUE) VALUES('A')
INSERT INTO DUMMY1(VALUE) VALUES('B')
INSERT INTO DUMMY1(VALUE) VALUES('C')
INSERT INTO DUMMY1(VALUE) VALUES(NULL)
INSERT INTO DUMMY1(VALUE) VALUES(NULL)
INSERT INTO DUMMY1(VALUE) VALUES('F')
INSERT INTO DUMMY1(VALUE) VALUES('R')
INSERT INTO DUMMY1(VALUE) VALUES('D')
INSERT INTO DUMMY1(VALUE) VALUES(NULL)
INSERT INTO DUMMY1(VALUE) VALUES('T')
INSERT INTO DUMMY1(VALUE) VALUES('R')
INSERT INTO DUMMY1(VALUE) VALUES(NULL)
SQL tables represent unordered sets. Your question makes no sense, unless I assume that that rows are ordered. This requires a separate column for the ordering.
Let me assume that you have such a column, which I will call id. Then, you can use a cumulative count to assign the groups and then aggregate:
SELECT STRING_AGG(value, '') WITHIN GROUP (ORDER BY id)
FROM (SELECT d.*,
SUM(CASE WHEN VALUE IS NULL THEN 1 ELSE 0 END) OVER (ORDER BY id) as grp
FROM DUMMY1 d
) d
WHERE value IS NOT NULL
GROUP BY grp;
Here is a db<>fiddle.
You can try below:
SELECT value from STRING_SPLIT
(
(select SUBSTRING(
(
SELECT ''+ isnull(Value,',')
FROM DUMMY1
FOR XML PATH('')
), 1 , 9999)),
',') as SS
where SS.value <> ''
Table 1:
Id1 Data1
123123 David
123124 Jan
1231344 Juro
1234126 Marco
Table 2:
Id2 Data2
1231230 Info 1
1231231 Info 2
1231232 Info 3
1231240 Info 4
1231241 Info 5
1231242 Info 6
Each id from Table 1 can have 1 or more matches in Table 2 based on first 6 digits.
For example 123123 from Table 1 matches 1231230, 1231231 and 1231232 in Table 2.
I'm trying to create join to match maximum id2 from Table 2 based on id1 from Table 1.
I would just join using LIKE:
SELECT
tb1.id1,
tb1.data1
MAX(tb2.[id2]) AS id2
FROM [dbo].[table1] tb1
LEFT JOIN [dbo].[table2] tb2
ON tb2.[id2] LIKE CONCAT(tb1.[id1], '%')
GROUP BY
tb1.id1,
tb1.data1
ORDER BY
tb1.id1 DESC;
This approach might still leave open the possibility of using an index on the second table. In any case, it is slightly easier to read than your version.
This is working solution:
SELECT tb1.*,
MAX(tb2.[id2]) as id2
FROM [dbo].[table1] tb1
LEFT JOIN [dbo].[table2] tb2
ON CASE
WHEN LEN(tb1.[id1]) = 7 and tb1.[id1] = tb2.[id2] THEN 1
WHEN LEN(tb1.[id1]) = 6 and tb1.[id1] = SUBSTRING(tb2.[id2],1,6) THEN 1
ELSE 0
END = 1
GROUP BY tb1.id1
,tb1.data1
ORDER BY tb1.id1 desc
You can try this as well:
Declare #t table (id1 varchar(50) , data1 varchar(50))
insert into #t values (123123,'David')
insert into #t values (123124,'Jan')
insert into #t values (1231344,'Juro')
Declare #t1 table (id2 varchar(50) , data2 varchar(50))
insert into #t1 values (1231230,'Info 1')
insert into #t1 values (1231231,'Info 2')
insert into #t1 values (1231232,'Info 3')
insert into #t1 values (1231240,'Info 4')
insert into #t1 values (1231241,'Info 5')
insert into #t1 values (1231242,'Info 6')
select * from #t a JOIN #t1 B
on b.id2 like '%' + a.id1 + '%'
I've got the following tables
Table1
Col1 | Col2
r1c1 | r1c2
r2c1 | r2c2
r3c1 | r3c2
r4c1 | r4c2
Table2
Col1_Table1 | Col2
r1c1_table1 | r1c2
r2c1_table1 | r2c2
r3c1_table1 | r3c2
So you see my row #4 is missing in Table2.
Select all rows from table 1 and join table 2. No Problem
But what looks the select like when I want to select all from Table1 but only if all from Table1 are in Table2? I hope you can understand.
In my example I the result of the select has to be zero/null.
If I understand you correctly, you want to return all rows of table 1 only if all of table 1 also exists in table 2
So in effect:
SELECT * FROM #table1
WHERE
(SELECT COUNT(*) FROM #table1)
= (SELECT COUNT(*) FROM #Table1 INNER JOIN #Table2 ON #Table1.col1 = #Table2.col1)
Is that correct? in which case a better way of doing this would be:
SELECT *
FROM #table1
WHERE NOT EXISTS (
SELECT 1
FROM #table1
WHERE col1 NOT IN (SELECT col1 FROM #table2)
);
Hi Please see example below
IF OBJECT_ID('tempdb..#Table1') IS NOT NULL
BEGIN
DROP TABLE #Table1
END
IF OBJECT_ID('tempdb..#Table2') IS NOT NULL
BEGIN
DROP TABLE #Table2
END
CREATE TABLE #Table1 (
Col1 NVARCHAR(20)
, Col2 NVARCHAR(20)
)
INSERT INTO #Table1 VALUES ('r1c1', 'r1c2')
INSERT INTO #Table1 VALUES ('r2c1', 'r2c2')
INSERT INTO #Table1 VALUES ('r3c1', 'r3c2')
INSERT INTO #Table1 VALUES ('r4c1', 'r4c2')
CREATE TABLE #Table2 (
Col1_Table1 NVARCHAR(20)
, Col2 NVARCHAR(20)
)
INSERT INTO #Table2 VALUES ('r1c1_table1','r1c2')
INSERT INTO #Table2 VALUES ('r2c1_table1','r2c2')
INSERT INTO #Table2 VALUES ('r3c1_table1','r3c2')
SELECT COUNT(*) as 'Result'
FROM #Table1 AS t1
INNER JOIN #Table2 AS t2
ON t1.Col1 = t2.Col2
IF OBJECT_ID('tempdb..#Table1') IS NOT NULL
BEGIN
DROP TABLE #Table1
END
IF OBJECT_ID('tempdb..#Table2') IS NOT NULL
BEGIN
DROP TABLE #Table2
END
Hope it helps
I think you are looking for INTERSECT.
Ex:
select Col1, Col2 from table1
INTERSECT
select Col1, Col2 from table2
Intersect will return results based on data being in BOTH tables.
Reference: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql?view=sql-server-2017
I am looking for a query which fetches me the data that is different compared to the previous row,
A sample code (with table creation and data)
create table #temp
(id int, eid int, name char(10),estid int, ecid int, epid int, etc char(5) )
insert into #temp values (1,1,'a',1,1,1,'a')
insert into #temp values (2,1,'a',1,1,1,'a')
insert into #temp values (3,1,'a',2,1,1,'a')
insert into #temp values (4,1,'a',1,1,1,'a')
insert into #temp values (5,1,'a',1,1,1,'a')
insert into #temp values (6,1,'a',1,2,1,'a')
insert into #temp values (7,1,'a',1,1,1,'a')
insert into #temp values (8,1,'a',2,1,1,'a')
insert into #temp values (9,1,'a',1,1,1,'a')
insert into #temp values (10,1,'a',1,1,1,'a')
insert into #temp values (11,2,'a',1,1,1,'a')
insert into #temp values (12,2,'a',1,1,1,'a')
insert into #temp values (13,2,'a',2,1,1,'a')
insert into #temp values (14,2,'a',1,1,1,'a')
insert into #temp values (15,2,'a',1,1,1,'a')
insert into #temp values (16,2,'a',1,2,1,'a')
insert into #temp values (17,2,'a',1,1,1,'a')
insert into #temp values (18,2,'a',2,1,1,'a')
insert into #temp values (19,2,'a',1,1,1,'a')
insert into #temp values (20,2,'a',1,1,1,'a')
I tried with some ways of getting the data as the way that i expected
SELECT * INTo #Temp_Final
FROM #temp
WHERE #temp.%%physloc%%
NOT IN (SELECT Min(b.%%physloc%%)
FROM #temp b
GROUP BY eid,name,estid,ecid,epid,etc)
ORDER BY id
SELECT * FROM #temp WHERE id not in (SELECT id FROM #Temp_Final) ORDER BY id
But i wasn't getting the result as i expected...
This is how the result needs to be
select * from #temp where id in (1,3,4,6,7,8,9,11,13,14,16,17,18,19)
You can do this with a simple self-join and appropriate comparison:
select t.*
from #temp t left outer join
#temp tprev
on t.id = tprev.id + 1
where tprev.id is null or
t.name <> tprev.name or
t.estid <> tprev.estid or
t.ecid <> tprev.ecid or
t.epid <> tprev.epid or
t.etc <> tprev.etc;
This assumes that the ids are sequential with no gaps. If the ids are not, you can get the previous id using a correlated subquery or the lag() function.
Your title says "delete" but the question seems to just want the list of such rows. You can phrase this as a delete query if you need to.
For SQL Server 2012 (SQL Fiddle)
WITH CTE
AS (SELECT *,
LAG(eid) OVER (ORDER BY id) AS prev_eid,
LAG(name) OVER (ORDER BY id) AS prev_name,
LAG(estid) OVER (ORDER BY id) AS prev_estid,
LAG(ecid) OVER (ORDER BY id) AS prev_ecid,
LAG(epid) OVER (ORDER BY id) AS prev_epid,
LAG(etc) OVER (ORDER BY id) AS prev_etc
FROM #temp)
DELETE FROM CTE
WHERE EXISTS (SELECT eid,
name,
estid,
ecid,
epid,
etc
INTERSECT
SELECT prev_eid,
prev_name,
prev_estid,
prev_ecid,
prev_epid,
prev_etc)
select
t.id,
t.eid,
t.name,
t.estid,
t.ecid,
t.epid,
t.etc
from #temp t
left join #temp d
on d.id = t.id-1
and d.eid = t.eid
and d.name = t.name
and d.estid = t.estid
and d.ecid = t.ecid
and d.epid = t.epid
and d.etc = t.etc
where d.id is null