Append parent table column value to child table column in sql - sql-server

Assume I have two tables, as below:
Table 1
ID Name
------------------
1 Adam
2 Eve
Table 2
ID FK_ID (Table 1) Name
--------------------------------------------
1 1 Chris
2 1 Austin
3 1 Steve
4 2 Charles
5 2 Erik
6 2 Austin
Required table as Result
ID Name
-----------------
1 Chris
2 Austin Adam
3 Steve
4 Charles
5 Erik
6 Austin Eve
Notice here, in the resulting table I want repeated "Austin" appended with "Adam/Eve" from parent table (i.e. Table 1), depending on "FK_ID". I want to do this in SQL. Any idea/help would really be appreciated.

You can use GROUP BY Name to check names with count(*) > 1 and then do a LEFT JOIN to append T1 names appropriately
Sample Data
CREATE TABLE Table1
([ID] int, [Name] varchar(4));
INSERT INTO Table1
([ID], [Name])
VALUES
(1, 'Adam'),
(2, 'Eve');
CREATE TABLE Table2
([ID] int, [FK_ID] int, [Name] varchar(7));
INSERT INTO Table2
([ID], [FK_ID], [Name])
VALUES
(1, 1, 'Chris'),
(2, 1, 'Austin'),
(3, 1, 'Steve'),
(4, 2, 'Charles'),
(5, 2, 'Erik'),
(6, 2, 'Austin');
Query
SELECT
T2.ID,
T2.Name + CASE WHEN T3.Name IS NOT NULL THEN ' ' + T1.Name ELSE '' END as Name
FROM Table2 T2
INNER JOIN Table1 T1 ON T2.[FK_ID] = T1.id
LEFT JOIN (SELECT Name FROM Table2 GROUP BY Name HAVING COUNT(*) > 1) T3 ON T2.Name = T3.Name
Output
ID Name
1 Chris
2 Austin Adam
3 Steve
4 Charles
5 Erik
6 Austin Eve

You can use a window count to determine whether a name is repeated or not:
SELECT t2.ID,
CONCAT(t2.Name,
IIF(COUNT(t2.Name) OVER(PARTITION BY t2.Name) > 1,
COALESCE(' ' + t1.Name, ''),
''))
FROM TABLE2 AS t2
LEFT JOIN TABLE1 AS t1 ON t2.FK_ID = t1.ID

SELECT ID,NAME
FROM TABLE2
WHERE NAME NOT IN (
SELECT NAME
FROM TABLE2
GROUP BY NAME
HAVING COUNT(*) >1 )
UNION
SELECT A.ID AS ID,A.NAME+' '+B.NAME AS NAME
FROM TABLE2 AS A INNER JOIN TABLE1 AS B
ON A.FK_ID = B.ID
WHERE NAME IN (
SELECT NAME
FROM TABLE2
GROUP BY NAME
HAVING COUNT(*) >1 )
ORDER BY ID
Using union to process the logic by two group.

Related

MSSQL: How to remove duplicate column values from different tables?

How to remove duplicate column values from different tables?
Given the following tables without foreign key reference:
Table A
Id IdentifierString
-------------------
1 String A
2 String B
3 String C
Table B
Id IdentifierString
-------------------
1 String A
2 String C
3 String D
I want to remove all duplicate column values:
Table A
Id IdentifierString
-------------------
1 NULL
2 String B
3 NULL
Table B
Id IdentifierString
-------------------
1 NULL
2 NULL
3 String D
How is this doable?
This could be done using UNION ALL, HAVING(COUNT ) and UPDATE statement as below:
CREATE TABLE Table1 (Id INT, IdentifierString VARCHAR (20));
INSERT INTO Table1 (Id, IdentifierString) VALUES
(1, 'String A'),
(2, 'String B'),
(3, 'String C');
CREATE TABLE Table2 (Id INT, IdentifierString VARCHAR (20));
INSERT INTO Table2 (Id, IdentifierString) VALUES
(1, 'String A'),
(2, 'String C'),
(3, 'String D');
DECLARE #DuplicateEntries TABLE (IdentifierString VARCHAR(20));
INSERT INTO #DuplicateEntries (IdentifierString)
SELECT IdentifierString FROM (
SELECT IdentifierString FROM Table1
UNION ALL
SELECT IdentifierString FROM Table2
) A
GROUP BY IdentifierString
HAVING COUNT(IdentifierString) > 1;
UPDATE T1
SET T1.IdentifierString = NULL
FROM Table1 T1
JOIN #DuplicateEntries D ON D.IdentifierString = T1.IdentifierString;
UPDATE T2
SET T2.IdentifierString = NULL
FROM Table2 T2
JOIN #DuplicateEntries D ON D.IdentifierString = T2.IdentifierString;
SELECT * FROM Table1;
SELECT * FROM Table2;
Please find the working demo on db<>fiddle
Here's your dml script to remove duplicates.
delete from table1 where id in (select id from (
select id, t1.IdentifierString, t2.IdentifierStringfrom table1 t1
left join table2 t2 on t2.IdentifierString= t1.IdentifierString) as t3
where isnull(t1.IdentifierString, '') = '' or isnull(t2.IdentifierString, '') = '')
delete from table2 where id in (select id from (
select id, t1.IdentifierString, t2.IdentifierStringfrom table2 t1
left join table1 t2 on t2.IdentifierString= t1.IdentifierString) as t3
where isnull(t1.IdentifierString, '') = '' or isnull(t2.IdentifierString, '') = '')

SQL Server: How to select missing rows in table from another table?

I have two tables like below:
table1:
StoreId SKU
------------
1 abc
2 abc
3 abc
1 xyz
4 xyz
table2:
StoreId
--------
1
2
3
4
5
I want to select missing storeid from the table1 which are in table 2. But condition is that in above example for SKU abc storeid 4 and 5 are missing and for sku xyz 2,3,5 are missing. So I want below table as output
SKU,ID
------
abc 4
abc 5
xyz 2
xyz 3
xyz 5
I am able to pull only the overall missing store which is 5 using below query.
SELECT
SKU, t2.StoreId
FROM
#table1 t1
FULL OUTER JOIN
#table2 t2 ON t1.StoreId = t2.StoreId
WHERE
t1.StoreId IS NULL
Below is test create and insert query.
Declare #table1 As table
(
StoreId varchar(4),
SKU varchar(5)
)
Declare #table2 As table
(
StoreId int
)
BEGIN
Insert Into #table1(SKU,StoreId) values('abc',1)
Insert Into #table1(SKU,StoreId) values('abc',2)
Insert Into #table1(SKU,StoreId) values('abc',3)
Insert Into #table1(SKU,StoreId) values('xyz',1)
Insert Into #table1(SKU,StoreId) values('xyz',4)
Insert Into #table2(StoreId) values(1)
Insert Into #table2(StoreId) values(2)
Insert Into #table2(StoreId) values(3)
Insert Into #table2(StoreId) values(4)
Insert Into #table2(StoreId) values(5)
END
Thank you
You need to get a list of all skus and tables, and then show only rows which do not appear in table1:
select SKU, StoreID
from #table2 t2
cross join (select distinct sku from #table1) t1
where not exists (select 1 from #table1 table1
where table1.SKU = t1.SKU
and table1.StoreId = t2.StoreId)
Here is an alternative solution with the same result.
Syntax is very similar to the answer from #BeanFrog:
SELECT
t3.SKU, t2.StoreID
FROM
#table2 t2
CROSS JOIN
(SELECT distinct SKU
FROM #table1) t3
LEFT JOIN
#table1 t1
ON
t1.SKU = t3.SKU
and t1.StoreId = t2.StoreId
WHERE
t1.sku is null

SQL Server: How to select top rows of a group based on value of the column of that group?

I have two tables like below.
table 1
id rem
1 2
2 1
table 2
id value
1 abc
1 xyz
1 mno
2 mnk
2 mjd
EDIT:
#output
id value
1 abc
1 xyz
2 mnk
What i want to do is select top 2 rows of table2 with id one as rem value is 2 for id 1 and top 1 row with id 2 as its rem value is 1 and so on. I am using MS sqlserver 2012 My whole scenario is more complex than this. Please help.
Thank you.
EDIT : I know that i should have given what i have done and how i am doing it but for this particular part i don't have idea for starting. I could do this by using while loop for each unique id but i want to do it in one go if possible.
First, SQL tables represent unordered sets. There is no specification of which values you get, unless you include an order by.
For this purpose, I would go with row_number():
select t2.*
from table1 t1 join
(select t2.*,
row_number() over (partition by id order by id) as seqnum
from table2 t2
) t2
on t1.id = t2.id and t2.seqnum <= t1.rem;
Note: The order by id in the windows clause should be based on which rows you want. If you don't care which rows, then order by id or order by (select null) is fine.
Try This:
DECLARE #tbl1 TABLE (id INT, rem INT)
INSERT INTO #tbl1 VALUES (1, 2), (2, 1)
DECLARE #tbl2 TABLE (id INT, value VARCHAR(10))
INSERT INTO #tbl2 VALUES (1, 'abc'), (1, 'xyz'),
(1, 'mno'), (2, 'mnk'), (2, 'mjd')
SELECT * FROM #tbl1 -- your table 1
SELECT * FROM #tbl2 -- your table 2
SELECT id,value,rem FROM ( SELECT ROW_NUMBER() OVER (PARTITION BY T.ID ORDER BY T.ID) rowid,
T.id,T.value,F.rem FROM #tbl2 T LEFT JOIN #tbl1 F ON T.id = F.id ) A WHERE rowid = 1
-- your required output
Hope it helps.

MS SQL match table on multiple rows

I want to join two tables based on multiple rows, and can't find the correct way to do this.
The tables looks something like this :
table1
Id Location LocationNo
1 1 1
1 2 2
1 3 3
2 1 1
2 2 2
3 2 1
3 1 2
3 3 3
4 1 1
4 2 2
4 3 3
4 4 4
table2
Location LocationNo
1 1
2 2
3 3
I want to get the Id from table1 that match exactly the rows in table2.
I expect that the return should be Id 1.
I've tried the query bellow but the result are not the one expected.
SELECT t.Id
FROM table1 t1
WHERE EXISTS (SELECT 1
FROM table2 t2
WHERE t1.LocationId = t2.LocationId
AND t1.LocationNo = t2.LocationNo)
Any suggestions? Thanks.
EDIT :
table2
Location LocationNo
1 1
2 2
3 3
5 4
For this case I expect that the result should be null
Make use of Inner Join.
select t1.Id -- or t2.id, depends which table you want the ID from
from table1 t1
inner join table2 t2
on t1.LocationId = t2.LocationId
and t1.LocationNo = t2.LocationNo
Select Distinct t1.Id --< Use Distinct to return unique values only
From table1 t1
Inner Join table2 t2 --< Use Inner Join instead of "where exists"
On t1.LocationId = t2.LocationId
AND t1.LocationNo = t2.LocationNo
Update: It actually turned out to be more interesting than that: here we are looking for the exact match on all rows:
Select t1.Id
From table1 t1
Left Join table2 t2 --< Left Join to register NULLs from table2
On t1.LocationId = t2.LocationId
AND t1.LocationNo = t2.LocationNo
Group By t1.Id
Having --< Number of records from each table equals the count of matching criteria rows
Count(t1.LocationId) = (Select Count(*) From table2)
AND Count(t2.LocationId) = (Select Count(*) From table2)
Source data for testing:
With table1 As (
Select * From (Values
(1, 1, 1),
(1, 2, 2),
(1, 3, 3),
(2, 1, 1),
(2, 2, 2),
(3, 2, 1),
(3, 1, 2),
(3, 3, 3),
(4, 1, 1),
(4, 2, 2),
(4, 3, 3),
(4, 4, 4)
) V (Id, LocationId, LocationNo)
), table2 As (
Select * From (Values
(1, 1),
(2, 2),
(3, 3)
) V (LocationId, LocationNo)
)
I think you are looking for this
IF EXISTS(SELECT 1
FROM (SELECT Count(1) cnt,
id
FROM Table1 a
GROUP BY id) a
JOIN (SELECT t1.Id,
Count(1) cnt
FROM table1 t1
JOIN table2 t2
ON t1.[Location] = t2.[Location]
AND t1.LocationNo = t2.LocationNo
GROUP BY t1.Id
HAVING Count(1) = (SELECT Count(1)
FROM table2)) b
ON a.cnt = b.cnt
AND a.Id = b.id)
WITH tot_count
AS (SELECT Count(1) cnt,
id
FROM #Table1 a
GROUP BY id),
sub_cnt
AS (SELECT t1.Id,
Count(1) cnt
FROM table1 t1
JOIN table2 t2
ON t1.[Location] = t2.[Location]
AND t1.LocationNo = t2.LocationNo
GROUP BY t1.Id
HAVING Count(1) = (SELECT Count(1)
FROM table2))
SELECT b.id
FROM tot_count a
JOIN sub_cnt b
ON a.cnt = b.cnt
AND a.Id = b.id
ELSE
SELECT NULL

How to make query to count values from two tables

I have three tables main 'maintable' table and two sub tables 'table1' and 'table2' the main table 'maintable' contains tow columns 'ID' and 'name' like that:
ID name
.... ......
1 Khalid
2 Jone
3 Steve
and the first sub table 'table1' contains 't1ID' and 'column' and 'ID' (foreign key) from 'maintable' like that:
t1ID column ID
...... ....... ....
1 Value 1
2 Value 1
3 Value 1
4 Value 2
and the second sub table 'table2' contains 't2ID' and 'column' and 'ID' (foreign key) from 'maintable' like that:
t2ID column ID
...... ....... ....
1 Value 2
2 Value 1
3 Value 1
4 Value 3
I want to make query to find count of (table1.ID) as A and count of (table2.ID) as B like that:
name A B
...... ... ...
khalid 3 2
Jone 1 1
Steve 0 1
Try this :
select name,
(select count(t1.ID) from table1 t1 where t1.ID = main.ID) as A,
(select count(t2.ID) from table2 t2 where t2.ID = main.ID) as B
from maintable main
Try this out:
;with cte1 as (
SELECT ID, COUNT(1) AS Cnt
FROM table1
GROUP BY ID
), cte2 as (
SELECT ID, COUNT(1) AS Cnt
FROM table2
GROUP BY ID
)
SELECT m.name, ISNULL(cte1.Cnt, 0) AS A, ISNULL(cte2.Cnt, 0) AS B
FROM maintable m
LEFT JOIN cte1 ON cte1.ID = m.ID
LEFT JOIN cte2 ON cte2.ID = m.ID
It can also be done with subqueries, but I like CTEs more (query is more readable).
Try this:
with t0_t1 as (
select
t.id,
t.nm,
count(t1.id) as A
from table0 t
left join table1 t1 on t.id = t1.id
group by t.id, t.nm
)
select t.nm, t.A, count(t2.id) as B
from t0_t1 t
left join table2 t2 on t.id = t2.id
group by t.nm, t.A
Example: http://sqlfiddle.com/#!6/341ff/10
create table table0 (id int, nm varchar(20));
insert into table0 values (1,'Khalid'),(2,'Jone'),(3,'Steve');
create table table1 (t1id int, col varchar(20), id int);
insert into table1 values
(1, 'v', 1), (2, 'v', 1), (3, 'v', 1), (4, 'v', 2);
create table table2 (t2id int, col varchar(20), id int);
insert into table2 values
(1, 'v', 2), (2, 'v', 1), (3, 'v', 1), (4, 'v', 3);
Result:
| nm | A | B |
|--------|---|---|
| Steve | 0 | 1 |
| Jone | 1 | 1 |
| Khalid | 3 | 2 |

Resources