merging two tables with a query - sql

I'm newbie to sql.
There are two different tables with same columns and assume that Name unique.
TABLE_A
Name | AGE
-----------
Toby | 2
Milo | 1
Achmed| 3
TABLE_B
Name | AGE
-----------
Milo | 2
TABLE_B is my superior table, If TABLE_B name value contains in TABLE_A, than TABLE_B's value should be selected. RESULT is shown below.
RESULT is not a table, the result of query.
RESULT
Name | AGE
-----------
Toby | 2
Milo | 2
Achmed| 3
I have already solve this problem on the programming side, but I'm curries about the sql query to get this result.
TSQL or PLSQL doesnt matter.

You can use FULL JOIN to get all rows from both tables and COALESCE to give precedence to Table_B if Name exists in both tables.
SELECT
COALESCE (b.Name, a.Name) as Name
,COALESCE (b.Age, a.Age) as Age
FROM Table_A a
FULL JOIN Table_B b ON a.Name = b.Name
SQLFiddle DEMO

You can "fuse" both results using a union like this
SELECT Name, AGE FROM TABLE_A
UNION
SELECT Name, AGE FROM TABLE_B
ORDER BY Name;
The SQL statement selects all the different Names and Ages from the "TABLE_A" and the "TABLE_B" tables.

You could also eliminate any duplicates while using union, I think this would be faster than a full join:
SELECT Name, Age FROM Table_B
UNION
SELECT Name, Age FROM Table_A WHERE TABLE_A.NAME NOT IN (SELECT Name FROM Table_B)
ORDER BY Name;

Related

SQL query for replacing null values in all columns of a row with values taken from rows of another table with matching ID

for example , let us say i have a table A which looks like this
ID
Country
Name
EmployeeCode
123
NULL
NULL
NULL
456
NULL
DAN
2258
and then i have another table B which looks like this
ID
Country
Name
EmployeeCode
123
US
MARY
3247
456
GERMANY
JOHN
1228
I would like the resulting table to look like this
ID
Country
Name
EmployeeCode
123
US
MARY
3247
456
GERMANY
DAN
2258
In other words, keep the information that is present in table A and replace all Null values for ALL columns (in the example above i wrote just 3 columns for the sake of simplicity, the actual number of columns I need to work on is much higher) in table A from rows in table B which have matching ID. Any suggestions would be highly appreciated. Thank you
Just use coalesce:
coalesce(value1, value2[, ...]) - Returns the first non-null value in the argument list. Like a CASE expression, arguments are only evaluated if necessary.
Something like:
SELECT a.ID
, coalesce(a.Country, b.Country)
, coalesce(a.Name, b.Name)
, coalesce(a.EmployeeCode, b.EmployeeCode)
FROM tableA a
LEFT JOIN tableB b on a.ID = b.ID
I believe the below code should do what you want :
Select
A.ID
,isnull(A.Country,B.Country)
,isnull(A.Name,B.Name)
,isnull(A.EmployeeCode,B.EmployeeCode)
from table1 A
left join table2 B
on A.ID = B.ID

insert into with two selects and compare

It looks stupid in this example but here is what I want to do:
Table_a:
id fk_b_id full_name
1 [I want '10' here] [I want 'John, Doe' here]
Table_b:
id first_name
10 John
Table_c:
id full_name date
20 John, Doe 2020-01-01
I get all the full names that is not already in c and meets the criteria like this:
select distinct full_name
from Table_c
where full_name not in (
select full_name
from Table_a ) and date > GETDATE()
The result from the query should be inserted into Table_a together with Table_b's id (fk_b_id). So I need a compare between part of Table_a's full_name and Table_b's first_name to get the correct fk. I can do the compare like this:
where Table_b.first_name = LTRIM(RTRIM(RIGHT(Table_c.full_name, CHARINDEX(',', REVERSE(Table_c.full_name))-1 )))
Can I insert all the full names from table c (that meets the criteria) and the fk from table b (where their first names match) into table a in one query?
Sure, just use your condition to JOIN between tables B and C
INSERT INTO Table_a (fk_b_id, full_name)
SELECT DISTINCT b.id, c.full_name
FROM Table_c c
INNER JOIN Table_b b ON b.first_name = LTRIM(RTRIM(RIGHT(c.full_name, CHARINDEX(',', REVERSE(c.full_name))-1 )))
WHERE c.full_name not in (
select a.full_name
from Table_a a ) and c.date > GETDATE()
EDIT:
Also note, that if your table_a.full_name column can have NULL values, NOT IN sub-query will fail to give you expected results. I suggest rewriting it to use NOT EXISTS
WHERE NOT EXISTS
(SELECT * FROM Table_a WHERE Table_a.Full_Name = Table_c.FUll_Name )

SQL - Return all Rows Where at Least one has value 'Y'

My question is very similar to this previous post
SQL Query, get a columns if another columns equal to x
The only difference is I am joining two tables and the previous solution does not seem to work. Basically I have two Columns once the tables have been joined. I want all rows of a name, where at least one row for that name has "Shasta" as a location. For example,
Column 1 = Name (From Table 1)
Column 2 = Location (From Table 2)
Name | Location
-------------------
Bob | Shasta
Bob | Leaves
Sean | Leaves
Dylan | Shasta
Dylan | Redwood
Dylan | Leaves
Should Return:
Name | Location
--------------------
Bob | Shasta
Bob | Leaves
Dylan | Shasta
Dylan | Redwood
Dylan | Leaves
I tried the solution of the previous post
where x in
(
select distinct x
from table 1
where y like 'Shasta'
)
Unfortunately, it only returned:
Name | Location
--------------------
Bob | Shasta
Dylan | Shasta
You are looking for a WHERE EXISTS clause. As an illustration, let's assume you have the following query:
select a.Name, b.Location
from table1 a
join table2 b on a.TableBId = b.Id
You are looking to retrieve all rows in this query where there exists a row in the same query results with that Name and where Location = 'Shasta'. Therefore we can use the query as a derived table, match the Name and look for a Location = 'Shasta':
select a.Name, b.Location
from table1 a
join table2 b on a.TableBId = b.Id
where exists (
select 1
from
(
select a.Name, b.Location
from table1 a
join table2 b on a.TableBId = b.Id
) x --this is the same as the above query, as a derived table
where x.Name = a.Name --correlate the queries by matching the Name
and x.Location = 'Shasta' --look for the column value in question
)
Granted, you may be able to simplify this query and/or eliminate the derived table in the WHERE EXISTS clause, depending on the actual schema and what table1 and table2 represent.
Simply use EXISTS to return a row if there exists a row with same name and location Shasta:
select name, location
from tablename t1
where exists (select 1 from tablename t2
where t1.name = t2.name
and t2.locaion = 'Shasta')
I think you should do another subquery. I'll call the joinresult joinedTable as you didn't showed us the statement with which you build the table. But you can just switch the joinedTable for your statement. Then do
select * from joinedTable where name in (select name from joinedTable where location = 'Shasta');
Result is your wanted: 2x Bob, 3x Dylan
Heres a fiddle for it:
http://sqlfiddle.com/#!9/7584e/3

How to get same results without using distinct in query

I have a table with data like so:
[ID, Name]
1, Bob
1, Joe
1, Joe
1, Bob
I want to retrieve a list of records showing the relationship between the records with the same ID.
For instance, I want the following result set from my query:
Bob, Joe
Joe, Bob
Bob, Bob
Joe, Joe
This shows me the "from" and "to" for every item in the table.
I can get this result by using the following query:
SELECT DISTINCT [NAME]
FROM TABLE A
INNER JOIN TABLE B ON A.ID = B.ID
Is there anyway for me to achieve the same result set without the use of the "distinct" in the select statement? If I don't include the distinct, I get back 16 records, not 4.
The reason you get duplicate rows without DISTINCT is because every row of ID = x will be joined with every other row with ID = x. Since the original table has (1, "Bob") twice, both of those will be joined to every row in the other table with ID = 1.
Removing duplicates before doing a join will do two things: decrease the time to run the query, and prevent duplicate rows from showing up in the result.
Something like (using MySQL version of SQL):
SELECT L.NAME, R.NAME
FROM (SELECT DISTINCT ID, NAME FROM A) AS L
INNER JOIN (SELECT DISTINCT ID, NAME FROM B) AS R
ON L.ID = R.ID
Edit: is B an alias for table A?
In SQL and MY SQL
SELECT COLUMN_NAME FROM TABLE_NAME group by COLUMN_NAME
Have you tried using a group by clause?
select name
from table a
inner join table b
on a.id=b.id
group by name
That should get you the same thing as your distinct query above. As for the result set that you want, a simple self join should do it:
select name1,name2
from(
select id,name as name1
from table
group by 1,2
)a
join(
select id,name as name2
from table
group by 1,2
)b
using(id)
Eliminating duplicate values with union without using distinct
Declare #TableWithDuplicateValue Table(Name Varchar(255))
Insert Into #TableWithDuplicateValue Values('Cat'),('Dog'),('Cat'),('Dog'),('Lion')
Select Name From #TableWithDuplicateValue
union
select null where 1=0
Go
Output
---------
Cat
Dog
Lion
For more alternate kindly visit my blog
http://www.w3hattrick.com/2016/05/getting-distinct-rows-or-value-using.html

View over multiple tables containing same columns

I have four tables containing exactly the same columns, and want to create a view over all four so I can query them together.
Is this possible?
(for tedious reasons I cannot/am not permitted to combine them, which would make this irrelevant!)
Assuming that in addition to having the same column names, columns of the same contain the same data, you want to create a view that is the union of all those tables.
Something like the following should work, but my SQL is rusty:
(CREATE VIEW view_name AS
(SELECT * FROM table1
UNION
SELECT * FROM table2
UNION
SELECT * FROM table3));
It may be worth noting that you might need to use "union all" to preserve unique rows which may exist in more than one of the tables. A standard union will remove duplicates.
It is difficult to tell from your query whether you expect the data to be returned based on a UNION, or as a view containing the columns discretely. This obviously has an effect.
Consider the following sample:
TableA
ID Name RelatedID
1 John 2
2 Paul 1
TableB
ID Name RelatedID
1 Ringo 1
2 George 1
TableC
ID Name RelatedID
1 Bob 1
TableD
ID Name RelatedID
1 Kate NULL
Now, run the following query against this:
SELECT ID, Name FROM TableA
UNION ALL
SELECT ID, Name FROM TableB
UNION ALL
SELECT ID, Name FROM TableC
UNION ALL
SELECT ID, Name FROM TableD
This results in the following output:
1 John
2 Paul
1 Ringo
2 George
1 Bob
1 Kate
Is this what you are after? If so, you use a UNION query.
Now, if the effect you are after is to have a discrete view of related data, you may need to do something like this:
SELECT A.ID MasterID, A.Name MasterName,
B.ID BandID, B.Name BandName,
C.ID BlackadderID, C.Name BlackadderName
D.ID BlackadderRealID, D.Name BlackadderRealName
FROM
TableA A
INNER JOIN
TableB B
ON
A.RelatedID = B.ID
INNER JOIN
TableC C
ON
B.RelatedID = C.ID
INNER JOIN
TableD D
ON
C.RelatedID = D.ID
This will result in the following view of the data:
MasterID MasterName BandID BandName BlackAdderID BlackAdderName BlackadderRealID BlackadderRealName
1 John 2 George 1 Bob 1 Kate
2 Paul 1 Ringo 1 Bob 1 Kate
Use union.
Here is explanation
Use the union statement
select * from table1
union
select * from table2
union
select * from table3
You can if you union them (I would suggest including some indicator as to which table each record came from):
select table1.column1, 1 as TableNumber
from table1
union
select table2.column1, 2 as TableNumber
from table2
.. etc ..
Rather than UNION, use UNION ALL, unless you specifically want duplicate rows to be excluded. UNION on its own takes longer to execute (because of the sort it does to find dupes), and removes duplicate rows.