How to properly construct SQL subquery in this code? - sql

When I execute the following code, I'm getting results such as:
ID column1 column2
34 NULL NULL
34 Org13 Org13
36 NULL NULL
36 NULL Org2
36 Org4 NULL
41 NULL NULL
41 NULL Org5
41 Org3 NULL
I want my results to look like:
ID column1 column2
34 Org13 Org13
36 Org4 Org2
41 Org3 Org5
I've got two tables: Table1 and Table2. Table2 is a lookup table with the following fields: id, name
Table1 has the following fields (id, column1, column2). column1 and column2 both have foreign key relationships to the lookup table:
FK_1: Table1.column1-Table2.id
FK_2: Table1.column2-Table2.id
Since I want to pull out the values for column1 and column2, and since both of these values are lookups on the same field (Table2.name), I suspect I need to do inner Selects.
My code is below. How can I change this so that it produces the results desired, instead of the ones I'm getting? Thanks in advance!
DECLARE #value INT
SET #value = 14
SELECT DISTINCT
Table1.[id] AS ID
, ( SELECT DISTINCT
Table2.[name]
WHERE
Table1.column1 =
Table2.id ) AS column1
, ( SELECT DISTINCT
Table2.[name]
WHERE
Table1.column2 =
Table2.id ) AS column2
FROM
Table1
,Table2
WHERE
Table1.[id] = #value

/*
create table table1(id int, col1 int, col2 int);
create table table2(id int, name varchar(10) );
insert into table2 values(1, 'org 1');
insert into table2 values(2, 'org 2');
insert into table2 values(3, 'org 3');
insert into table2 values(4, 'org 4');
insert into table1 values(1, 1, 2);
insert into table1 values(2, 2, 2);
insert into table1 values(3, 2, 3);
insert into table1 values(4, 4, 1);
*/
select
a.id,
b.name as column1,
c.name as column2
from
table1 a
join table2 b on b.id = a.col1
join table2 c on c.id = a.col2;
id column1 column2
----- ---------- ----------
1 org 1 org 2
2 org 2 org 2
3 org 2 org 3
4 org 4 org 1
4 record(s) selected [Fetch MetaData: 3/ms] [Fetch Data: 0/ms]
[Executed: 7/7/09 4:07:25 PM EDT ] [Execution: 1/ms]

gbn, I think you meant to write
DECLARE #value INT
SET #value = 1
SELECT --??? DISTINCT
t1.[id] AS ID, --- missed comma
table2a.name,
table2b.name
FROM
Table1 t1
JOIN Table2 table2a ON t1.column1 = table2a.id
JOIN Table2 table2b ON t1.column2 = table2b.id -- you have t1.column1 oops
WHERE
t1.[id] = #value

DECLARE #value INT
SET #value = 14
SELECT
t1.[id] AS ID
MAX(t2a.name),
MAX(t2b.name)
FROM
Table1 t1
LEFT JOIN
Table2 t2a ON t1.column1 = t2a.id
LEFT JOIN
Table2 t2b ON t1.column2 = t2b.id
WHERE
t1.[id] = #value
GROUP BY
t1.[id]

Related

JOIN tables based on 6 or 7 digits key in 1st table with 7 digits key in second table by using CASE and MAX function

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 + '%'

Select rows from two tables only whenn 'all in'

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

Match the codes and copy columns

I am working in SQL Server 2008. I have 2 tables Table1 & Table2.
Table1 has columns
SchoolCode, District, Type, SchoolName
and Table2 has columns
SchoolCode1, District1, Type1, SchoolName1
SchoolCode columns in both tables have the same codes like "1234"; code is the same in both schoolcode columns.
Now I want to copy the District, Type and SchoolName column values from Table1 to Table2 if SchoolCode in both tables is same.
I think the query will use join but I don't know how it works. Any help on how I can do this task?
Maybe use an update statement in join if by copying over you mean updating rows
update t2
set
District1= District,
Type1= Type,
SchoolName1= SchoolName
from Table1 t1
join
Table2 t2
on t1.SchoolCode=t2.SchoolCode1
I could give you a little bit of idea. here is it:
Insert into table2 (District1, Type1, SchoolName1)
SELECT District, Type, SchoolName
FROM table1
where table1.Schoolcode=table2.Schoolcode1
You have to use Inner join to update data from table 1 to table 2, Inner join will join values that are equal. . To learn more about joins, I highly recommend you to read the below article
SQLServer Joins Explained - W3Schools
Please refer the below code, for the convenience I have used the temporary tables..
DECLARE #Table1 TABLE
(
SchoolCode INT,
District VARCHAR(MAX),
Type VARCHAR(MAX),
SchoolName VARCHAR(MAX)
)
DECLARE #Table2 TABLE
(
SchoolCode1 INT,
District1 VARCHAR(MAX),
Type1 VARCHAR(MAX),
SchoolName1 VARCHAR(MAX)
)
INSERT INTO #Table1
( SchoolCode ,District , Type , SchoolName
)
VALUES ( 1 ,'DIS1' ,'X' ,'A'),
( 2 ,'DIS2' ,'Y' ,'B'),
( 3 ,'DIS3' ,'Z' ,'C'),
( 4 ,'DIS4' ,'D' ,'D'),
( 5 ,'DIS5' ,'K' ,'E')
INSERT INTO #Table2
( SchoolCode1 ,District1 , Type1 , SchoolName1
)
VALUES ( 1 ,'DIS1' ,'X' ,'A'),
( 2 ,NULL ,'Z' ,NULL),
( 3 ,'DIS3' ,'Z' ,'C'),
( 4 ,NULL ,'Z' ,'S'),
( 5 ,'DIS5' ,'K' ,'E')
--BEFORE
SELECT * FROM #Table1
SELECT * FROM #Table2
--Logic UPDATE Table 2
UPDATE t2 SET t2.District1 = t1.District,
t2.Type1 = t1.Type,
t2.SchoolName1 = t1.SchoolName
FROM #Table1 t1
INNER JOIN #Table2 t2 ON t1.SchoolCode = t2.SchoolCode1
-- End Logic UPDATE Table 2
--AFTER
SELECT * FROM #Table1
SELECT * FROM #Table2
You can join tables in an UPDATE statement.
Note, I have aliased the tables, table1 and table2 as t1 and t2 respectively.
This is what I did:
create table Table1
(SchoolCode varchar(50),
District varchar(50),[Type] varchar(50),SchoolName varchar(50))
go
create table Table2
(SchoolCode1 varchar(50), District1 varchar(50),[Type1] varchar(50),SchoolName1 varchar(50))
go
insert into table1 values ('1234','District1','High','Cool School')
insert into table1 values ('2222','District2','Lower','Leafy School')
insert into table2 (SchoolCode1) values ('1234')
go
update t2
set District1 = District,
Type1 = [Type],
SchoolName1 = SchoolName
from table1 t1
join table2 t2
on t2.SchoolCode1 = t1.SchoolCode
go
select * from table2
go

combining resultset of many select queries

I have four Select queries for four different tables, each extracting only one record. For example:
Select * from table where col1 = 'something'
gives one row having 3 columns.
The second select query also gives one record having two columns(fields). Same for third and fourth select query.
I want to combine all four result sets into one having one row. How is it possible?
I will write the queries for you.
1st one:
Select Top 1 column1, column2
from table 1
where column 1 = 'something'
and col1 = (Select max(col1) where column 1 = 'something')
2nd query:
Select Top 1 column1, column3
from table 2
where column 1 = 'something'
and column3 = (Select max(column3) where column 1 = 'something')
3rd query uses the result obtained from query 2:
Select column4
from table 3
where column3 = (obtained from 2nd query) (there is only one row)
4th:
Select column5
from table 4
where column3 = (obtained from 2nd query) (there is only one row)
This means I have to join 2nd, 3rd, 4th query, then resulting set in 1st.
I can't use union since columns are different.
So only problem is with joining the result set.
You can use CROSS JOINs to accomplish this.
CREATE TABLE table1 (id int, column1 varchar(5), column2 varchar(15));
CREATE TABLE table2 (column3 varchar(5), column4 varchar(15));
CREATE TABLE table3 (id int, column5 varchar(5), column6 varchar(15));
INSERT INTO table1 VALUES (1, 'aaa', 'row1')
INSERT INTO table2 VALUES ('bbb', 'table2')
INSERT INTO table3 VALUES (1, 'ccc', 'table3')
INSERT INTO table1 VALUES (1, 'ddd', 'table1')
SELECT * FROM (SELECT * FROM table1) a
CROSS JOIN (SELECT * FROM table2) b
CROSS JOIN (SELECT * FROM table3) c
Result:
id column1 column2 column3 column4 id column5 column6
1 aaa row1 bbb table2 1 ccc table3
1 ddd table1 bbb table2 1 ccc table3
Update after clarification:
CREATE TABLE table1
(
id int IDENTITY(1,1)
, searchstring nvarchar(25)
);
CREATE TABLE table2
(
id2 int IDENTITY(10, 10)
, searchstring2 nvarchar(25)
, newsearchstring nvarchar(50)
);
CREATE TABLE table3
(
id3 int IDENTITY(100, 100)
, id2 int
, table3srow nvarchar(25)
)
INSERT INTO table1 VALUES ('something');
INSERT INTO table1 VALUES ('something else');
INSERT INTO table1 VALUES ('something'); -- ID = 3, this row will be selected by 1st query
INSERT INTO table2 VALUES ('something', 'newvalue1');
INSERT INTO table2 VALUES ('something else', 'this will not be shown');
INSERT INTO table2 VALUES ('something', 'this will be returned by query 2'); -- ID = 30, this row will be selected by 2nd query
INSERT INTO table3 VALUES (10, 'not relevant');
INSERT INTO table3 VALUES (20, 'not relevant');
INSERT INTO table3 VALUES (30, 'This is from table 3'); -- This row will be returned by 3rd query
SELECT * FROM
(SELECT TOP 1 id, searchstring FROM table1 WHERE searchstring = 'something' and id = (SELECT MAX(id) FROM table1 WHERE searchstring = 'something')) AS query1,
(SELECT TOP 1 id2, newsearchstring FROM table2 WHERE searchstring2 = 'something' and id2 = (SELECT MAX(id2) FROM table2 WHERE searchstring2 = 'something')) AS query2,
(SELECT id2, table3srow FROM table3) as query3
WHERE query3.id2 = query2.id2
Use the same approach for table4 as indicated for table3.

interesting t-sql exercise

I am trying to resolve t-sql exercise
I need to update first table with values from second by joining by id. If I can not join then use value from default ID (default iD is the Id that is null)
please run it to see it
declare #t as table (
[id] INT
,val int
)
insert into #t values (null, null)
insert into #t values (2, null)
insert into #t values (3, null)
insert into #t values (4, null)
declare #t2 as table (
[id] INT
,val int
)
insert into #t2 values (null, 11)
insert into #t2 values (2, 22)
insert into #t2 values (3, 33)
select * from #t
select * from #t2
update t
set t.val = t2.val
from #t as t join #t2 as t2
on t.id = t2.id
or
(
(t.id is null or t.id not in (select id from #t2))
and t2.id is null
)
select * from #t
here is result
--#t
id val
---------------
NULL NULL
2 NULL
3 NULL
4 NULL
--#t2
id val
---------------
NULL 11
2 22
3 33
--#t after update
id val
---------------
NULL 11
2 22
3 33
4 NULL
how to make val in last row equal 11?
4 11
This solution left joins to t2 twice and then does a coalesce.
The ON on the second join matches on records that failed on the join and then looks for the "Default" case.
UPDATE t
set t.val = COALESCE(t2.val,t3.val)
from #t as t
LEFT join #t2 as t2
on t.id = t2.id
LEFT JOIN #t2 t3
ON t2.id is null and t3.id is null
See it working here
try this for the update...
update t
set t.val = t2.val
from #t as t join #t2 as t2
on t.id = t2.id
or
(
(t.id is null or not exists (select * from #t2 where id = t.id))
and t2.id is null
)
Problem is with not in operator and null values. This would also work...
update t
set t.val = t2.val
from #t as t join #t2 as t2
on t.id = t2.id
or
(
(t.id is null or t.id not in (select id from #t2 where id is not null))
and t2.id is null
)
Here's a technique that may help.
Start with the kind of simple code you want to be writing:
MERGE INTO #t AS target
USING source
ON target.id = source.id
WHEN MATCHED THEN
UPDATE
SET val = source.val;
Then write a table expression (source) that satisfies the requirements.
Requirement 1: "joining by id"
-- simple existential quantification e.g.
SELECT id, val
FROM #t2 AS T2
WHERE id IN ( SELECT id FROM #t )
Requirement 2: "If I can not join then use value from default ID (default iD is the Id that is null)"
-- first find the id values in the target that do not exist in the source:
SELECT id
FROM #t
EXCEPT
SELECT id
FROM #t2
then cross join the result with the row from the source where Id is null:
SELECT DT1.id, T2.val
FROM ( SELECT id
FROM #t
EXCEPT
SELECT id
FROM #t2 ) AS DT1,
#t2 AS T2
WHERE T2.id IS NULL
At this point you will want to query some test data to ensure each query satisfies its respective requirement.
Union the above two results to form a single table expression:
SELECT id, val
FROM #t2 AS T2
WHERE id IN ( SELECT id
FROM #t )
UNION
SELECT DT1.id, T2.val
FROM ( SELECT id
FROM #t
EXCEPT
SELECT id
FROM #t2 ) AS DT1,
#t2 AS T2
WHERE T2.id IS NULL
Then plug the table expression into the MERGE boilerplate code:
WITH source
AS
(
SELECT id, val
FROM #t2 AS T2
WHERE id IN ( SELECT id
FROM #t )
UNION
SELECT DT1.id, T2.val
FROM ( SELECT id
FROM #t
EXCEPT
SELECT id
FROM #t2 ) AS DT1,
#t2 AS T2
WHERE T2.id IS NULL
)
MERGE INTO #t AS target
USING source
ON target.id = source.id
WHEN MATCHED THEN
UPDATE
SET val = source.val;