How to merge data from two tables with some common fields - sql

So I have two tables that have similar data. There are columns in table A that match columns in table B, but with different naming conventions, there are also columns from each that have no equivalent in the other table, no rows should be merged, I need a view (I think) with all the rows from both tables, but with some columns merged so that data from table A.columnB and data from table B.columnF both end up in view C.columnD. There would be columns in the view that only had sources in one of the tables and would be null in rows from the other table. I can't change any of the existing table structure as the database is shared across multiple apps. I think I need to use a bunch of FULL OUTER JOIN statements in the view but I'm having trouble wrapping my mind around how to really go about it. If anyone can provide a generic example of how this should look I should be able to take it from there.
Here's an example of what doesn't work (there are a lot more columns on each side of the JOIN in the actual db, truncated for readability):
SELECT
schedule_block.id as vid,
schedule_block.reason as vreason,
schedule_block.when_ts as vwhen,
schedule_block.duration as vduration,
schedule_block.note as vnote,
schedule_block.deleted_ts as vdeleted_when,
schedule_block.deleted_user_id as vdeleted_user_id,
schedule_block.lastmodified_ts as vlastmodified_ts,
schedule_block.lastmodified_user_id as vlastmodified_user_id
FROM schedule_block
FULL OUTER JOIN appointment.appt_when as vwhen ON 1 = 1
FULL OUTER JOIN appointment.patient_id as vpatient ON 1 = 1
FULL OUTER JOIN appointment.duration as vduration on 1 = 1
FULL OUTER JOIN appointment.deleted_when as vdeleted_when ON 1 = 1
Correct me if I'm wrong but I think I can't use a UNION because there are different numbers of columns on each side

You could do something like:
SELECT ColA, CONVERT(DATE, NULL) AS ColB
FROM T1
UNION ALL
SELECT CONVERT(VARCHAR(10), NULL) AS ColA, ColB
FROM T2
Just make sure to match the datatypes.

Related

Best way to combine two tables, remove duplicates, but keep all other non-duplicate values in SQL

I am looking for the best way to combine two tables in a way that will remove duplicate records based on email with a priority of replacing any duplicates with the values in "Table 2", I have considered full outer join and UNION ALL but Union all will be too large as each table has several 1000 columns. I want to create this combination table as my full reference table and save as a view so I can reference it without always adding a union or something to that effect in my already complex statements. From my understanding, a full outer join will not necessarily remove duplicates. I want to:
a. Create table with ALL columns from both tables (fields that don't apply to records in one table will just have null values)
b. Remove duplicate records from this master table based on email field but only remove the table 1 records and keep the table 2 duplicates as they have the information that I want
c. A left-join will not work as both tables have unique records that I want to retain and I would like all 1000+ columns to be retained from each table
I don't know how feasible this even is but thank you so much for any answers!
If I understand your question correctly you want to join two large tables with thousands of columns that (hopefully) are the same between the two tables using the email column as the join condition and replacing duplicate records between the two tables with the records from Table 2.
I had to do something similar a few days ago so maybe you can modify my query for your purposes:
WITH only_in_table_1 AS(
SELECT *
FROM table_1 A
WHERE NOT EXISTS
(SELECT * FROM table_2 B WHERE B.email_field = A.email_field))
SELECT * FROM table_2
UNION ALL
SELECT * FROM only_in_table_1
If the columns/fields aren't the same between tables you can use a full outer join on only_in_table_1 and table_2
try using a FULL OUTER JOIN between the two tables and then a COALESCE function on each resultset column to determine from which table/column the resultset column is populated

SQL: Combine two tables, into same columns, based on relation table

Not being well versed in complex SQL, I am trying to figure out how I can write a query that will return (almost) the same columns from two tables, based on a "relationship" table. I have tried using UNION, but the number of columns are different between the three tables. I also tried IF...ELSE, but could not get that to function. I have also looked at INCLUDE and EXCLUDE.
Here is my current query:
SELECT
/* Relation Table */
[data_Related_Asset].[ID_Related_Asset]
,[data_Related_Asset].[BIOMED_Tag]
,[data_Related_Asset].[Related_BIOMED_Tag]
/* Lab Table */
,[data_Lab_Asset].[Room]
,[Lab_Area].[Work_Area]
,[data_Lab_Asset].[Pet_Name_Bench]
,[data_Lab_Asset].[BGL_ID]
,[data_Lab_Asset].[BIOMED_Tag] AS LAB_BIOMED
,[data_Lab_Asset].[Endpoint_Tag]
,[Lab_Class].[Class]
,[Lab_Class].[Subclass]
,[Lab_Class].[Subcategory]
/* IT Table */
,[data_IT_Asset].[Room]
,[IT_Area].[Work_Area]
,[data_IT_Asset].[Bench_Instrument]
,[data_IT_Asset].[BIOMED_Tag] AS IT_BIOMED
,[data_IT_Asset].[Endpoint_Tag]
,[IT_Class].[Class]
,[IT_Class].[Subclass]
,[IT_Class].[Subcategory]
FROM [data_Related_Asset]
LEFT JOIN [data_Lab_Asset] ON [data_Lab_Asset].[BIOMED_Tag] = [data_Related_Asset].[Related_BIOMED_Tag]
LEFT JOIN [data_IT_Asset] ON [data_IT_Asset].[BIOMED_Tag] = [data_Related_Asset].[Related_BIOMED_Tag]
LEFT JOIN [tbl_Class] Lab_Class ON [Lab_Class].[ID_Class] = [data_Lab_Asset].[Class_ID]
LEFT JOIN [tbl_Class] IT_Class ON [IT_Class].[ID_Class] = [data_IT_Asset].[Class_ID]
LEFT JOIN [tbl_Work_Area] Lab_Area ON [Lab_Area].[ID_Work_Area] = [data_Lab_Asset].[Work_Area_ID]
LEFT JOIN [tbl_Work_Area] IT_Area ON [IT_Area].[ID_Work_Area] = [data_IT_Asset].[Work_Area_ID]
ORDER BY ID_Related_Asset
The query is being used in a custom app and is set up to search for an "ID" in the [data_Related_Asset].[BIOMED_Tag] column, and return all [Related_BIOMED_Tag] records.
When I run the above query I get all the results I need, but across a lot of columns. If the item being return is in the LAB table, then the LAB_Asset columns are populated, but the IT_Asset columns are all NULL. And if the item is in the IT table, the opposite is true - the LAB_Asset columns are all NULL and the IT_Asset columns are populated. For example, below you can see where rows 2 & 12 returned the IT_Asset information.
I'd like to be able to return everything in the same set of NINE columns to condense the viewed table. (Room, Work_Area, Bench, BGL_ID, BIOMED_Tag, Endpoint_Tag, Class, Subclass, Subcategory) For example, below you can see where I moved the info from the IT_Asset table over to the first columns.
I'm sure I'm missing a simple solution/function here. Any help is greatly appreciated!
You can use UNION but you just have to ensure that you have the same columns in the same order in each statement being union'd.
So for missing columns just use nulls (or any suitable dummy data) e.g.
SELECT col1, col2, null, col4
from tableA
UNION
SELECT col1, null, col3, null
from tableB

SQL: Except Join on multiple queries

Getting a bit stuck trying to build this query. (SQL SERVER)
I'm trying to join two tables on similar rows, but then stack the unique rows from both table 1 and table 2 on the result set. I was first shooting for a full outer join, but it leaves my key fields blank when the data comes from only one of the tables.
Example: Full Outer Join
Here's what I would like for the query to be able to do:
Essentially, I would like to have a result table where the key fields (Part and Operation) are all returned in two columns (so like a union), but the Estimated and Actual Rate columns returned side by side where there is a matching row between table 1 and table 2.
I've also been trying to inner join the two tables to make a subquery, then using that inner join for except clause on each of the tables, then stacking the original inner join with the two except unions.
Current Attempt: One Join, Two Excepts, Two Unions
UPDATE: I got the current attempt to return values! It's a bit complicated though, Appreciate any advice or feedback though! Great answers below thanks, I will need to do some comparisons
Thanks
SELECT ISNULL(t1.part,t2.part) AS Part,
ISNULL(t1.operation,t2.operation) AS Operation,
ISNULL('Estimated Rate',0) AS 'Estimated Rate',
ISNULL('Actual Rate',0) AS 'Actual Rate'
FROM table1 t1
FULL OUTER JOIN table2 t2
ON t1.part = t2.part
AND t1.operation = t2.operation
I would do this as a union all and group by:
select part, operation,
sum(estimatedrate) as estimatedrate, sum(actualrate) as actualrate
from ((select part, operation, estimatedrate, 0 as actualrate
from table1
) union all
(select part, operation, 0 as estimatedrate, 0 actualrate
from table1
)
) er
group by part, operation;

SQL Server View tables not joining

I am incredibly new to SQL and am trying to create a view for a pizza store database. The sides ordered table and the sides names table have to be separate but need a view that combines them.
This is the code I have entered,
CREATE VIEW ordered_sides_view
AS
SELECT
ordered_side_id, side.side_id, side_name, number_ordered,
SUM(number_ordered * price) AS 'total_cost'
FROM
ordered_side
FULL JOIN
side ON ordered_side.side_id = side.side_id
GROUP BY
ordered_side_id, side.side_id, side_name, number_ordered;
The problem is that this is the resulting table.
Screenshot of view table:
How do I get the names to match the ordered sides?
You fail to understand what a FULL JOIN and an INNER JOIN operation does.
FULL JOIN returns at least every row from each table (plus any extra values from the ON clause).
INNER JOIN returns only matching row sets based on the ON clause.
OUTER JOIN returns every matching row set PLUS the side of the join that the OUTER JOIN is on (LEFT OUTER JOIN vs RIGHT OUTER JOIN).
In your picture, you can clearly see that there are no rows that match from the tables ordered_side and side...
That is why switching to an INNER JOIN returns zero rows...there are no matches on the COLUMNS YOU CHOSE TO USE.
Why in your SELECT operator do you have this:
SELECT ordered_side_id, side.side_id, side_name, number_ordered,
while your ON clause has this:
side ON ordered_side.side_id = side.side_id
ordered_side_id !=ordered_side.side_id
Investigate your columns and fix your JOIN clause to match the correct columns.
P.S. I like how you structure your queries. Very nice and what an
expert does! It makes reading MUCH, MUCH easier. :)
One suggestion I might add is structure your columns in the SELECT statement in its own row:
SELECT ordered_side_id
, side.side_id
, side_name
, number_ordered
, SUM(number_ordered * price) AS Total_Cost --or written [Total_Cost]/'Total_Cost'
FROM ordered_side
FULL JOIN side ON ordered_side.ordered_side_id = side.side_id
GROUP BY ordered_side_id
, side.side_id
, side_name
, number_ordered;

Inner join between two tables with same count values

I have been working on this issue since 2 days now.
I have two tables created by using SQL Select statements
SELECT (
) Target
INNER JOIN
SELECT (
) Source
ON Join condition 1
AND Join condition 2
AND Join condition 3
AND Join condition 4
AND Join condition 5
The target table has count value of 10,000 records.
The source table has count value of 10,000 records.
but when I do an inner join between the two tables on the 5 join conditions
I get 9573 records.
I am basically trying to find a one to one match between source and target table. I feel every field from target matches every field in source.
Questions:
Why does my inner join give less records even if there are same value of records in both tables?
If it is expected, how can I make sure I get the exact 10,000 records after the join condition?
1) An INNER JOIN only outputs the rows from the JOINING of two tables where their joining columns match. So in your case, Join Condition1 may not exist in rows in both tables and therefore some rows are filtering out.
2) As the other poster mentioned a left join is one way. You need to look which table source or target you want to use as your master i.e. start from and return all those rows. You then left join the remaining table based on your conditions to add all the columns where you join conditions match.
It's probably better if you give us the tables you are working on and the query\results you are trying to achieve.
There's some really good articles about the different joins out there. But it looks like you'd be interested in left joins. So if it exists in Target, but not in Source, it will not drop the record.
So, it would be:
SELECT(...) Target
LEFT OUTER JOIN
SELECT(...) Source
ON cond1 and cond2 and cond3 and cond4 and cond5
Give that a shot and let me know how it goes!
Sometime you need to rely on logical analysis rather than feelings. Use this query to find the fields that do not match and then work out your next steps
SELECT
Target.Col1,Source.Col1,
Target.Col2,Source.Col2,
Target.Col3,Source.Col3
FROM
(
) Target
FULL OUTER JOIN
(
) Source
ON Target.Col1=Source.Col1
AND Target.Col2=Source.Col2
AND Target.Col3=Source.Col3
WHERE (
Target.Col1 IS NULL
OR Source.Col1 IS NULL
OR Target.Col2 IS NULL
OR Source.Col2 IS NULL
OR Target.Col3 IS NULL
OR Source.Col3 IS NULL
)