Joining multiple tables with one to many relationship - c#

I have 3 tables:
maintable(id, serialno, col3, col4, col5, ..., col10)
table1(t1_id, serialno, t1_type, t1_color)
table2(t2_id, serialno, t2_base, t2_price)
maintable's Primary Key is id and serialno is UNIQUE.
Table1's Primary Key is t1_id and table2's is t2_id.
Table1 and Table2 serialno are Foreign Keys that reference MainTable's serialno.
maintable has a one to many relationship with both table1 and table2.
What I want to do is join these 3 tables in a DataTable.
I first thought that it would be simple and I tried: "SELECT * FROM maintable INNER JOIN table1 ON maintable.serialno = table1.serialno INNER JOIN table2 ON maintable.serialno= table2.serialno WHERE maintable.id = 200";
The problem with the result is that if table1 has 3 rows and table2 has 4 rows then my DataTable becomes 12 rows(3x4). What I want to do in this instance is just get 4 rows.
table1 and table2 columns don't have anything to do with each other and they only have to match maintable's serialno.
In case that I'm not being understood, I want to select the rows of table1 and table2 that match maintable's serialno and add them to the right of maintable without them getting duplicated.
Edit: Sorry, I had written accountno instead of serialno in some cases.

SELECT * FROM
maintable m
INNER JOIN (
SELECT t1.serialno, t1.t1_type, t1.t1_color, null as t2_base, null as t2_price
FROM table1 t1
UNION
SELECT t2.serialno, null as t1_type, null as t1_color, t2.t2_base, t2.t2_price
FROM table2 t2
) t ON m.serialno = t.serialno
ORDER BY m.serialno
This will do what you're asking for: return number of rows in t1 + number of rows in t2, rather than rows in t1 x number of rows in t2. Fiddle. This may not perform so hot if you have a large amount of data.
Now that you know how it's done, don't do it.
The real question is why is this a requirement? What are you really trying to accomplish here? This is not a meaningful way to combine the data from the two child tables, given their relationships. T1 and t2 are different tables and not keyed to each other for a reason: they aren't meant to combine their data like this.
The only new data I can imagine extracting from this kind of query is the total count of rows in both t1 and t2 for a given serial number. But there are much better ways to get this information than selecting the rows like this. If you need both t1 and t2 data and duplicates are throwing you off, odds are good that you should be making two separate SELECT statements instead of trying to combine everything.

SELECT
maintable.accountno
FROM
maintable
INNER JOIN table1 ON
maintable.accountno = table1.accountno
INNER JOIN table2 ON
maintable.accountno = table2.accountno
WHERE
maintable.id = 200
GROUP BY
maintable.accountno

Related

How to Select all records from table 1 and exclude matching records from table 2 using LINQ

I want to select all records from table 1 and if there any match between table 1 and table 2 then I have to exclude that records.
Note: The requirement is I have to use left outer join for that..
For example,
table 1 table 2
1 1
2 2
3
Output should be 3
I have written query in SQL but I want this in SQL LINQ like from a in dbContext.Table1....
select t1.*
from table1 t1
left outer join table2 t2 on t1.ID = t2.ID and t1.Code = t2.Code
where s.ID is null
How to solve this?
var result = (from primer in one
join primer2 in two on primer.id equals primer2.id into gj
where gj.Count()==0
select new
{
primer.id
}).ToList();
Where ONE - it is first table, TWO - it is second table.
Instead of
...select new
{
primer.id
}...
You can use
...
select primer
...

Function in SQL to diff values from 2 different tables and put the value to a third table

I have three tables (table1, table2, table3).
In table1 I have different values (some of them are same but it's ok), in table2 I also have different values (some of them are same but it's ok).
Now I want to create a function which is going to sum the same values of table1 sum the values from table2 and do a diff between the same values and insert that value in a specific column of table3.
table1:
KodikosBarcode total
1 14
2 18
table2:
KodikosBarcode total
1 1
2 2
table3 should have to be like this
KodikosBarcode total
1 13
2 16
Can someone help?
then table3 will have
table3:
KodikosBarcode total
1 13
2 16
3 1
Like this? (If MSSQL) but hopefully you get the idea anyway...
INSERT Table3
(SomeColumn)
SELECT
(SELECT Sum(SomeColumnFromTable1) FROM Table1) -
(SELECT Sum(SomeColumnFromTable2) FROM Table2)
To update you would do a similar thing;
UPDATE Table3
SET SomeColumn = (SELECT
(SELECT Sum(SomeColumnFromTable1) FROM Table1) -
(SELECT Sum(SomeColumnFromTable2) FROM Table2))
WHERE (whatever row you want to update... you didn't tell us)
for SQL Server:
insert into table 3
(
KodikosBarcode
, Diff_Value
)
select
t1.KodikosBarcode
t1.total - t2.total
from
table1 as t1
inner join table2 as t2
on t2.KodikosBarcode = t1.KodikosBarcode
This assumes that you only want the difference between rows where the bar code exists in both tables.
If you're doing an update to existing rows in the target table, you would use:
update t3 set
t3.total = t1.total - t2.total
from table3 as t3
inner join table1 as t1
on t1.KodikosBarcode = t3.KodikosBarcode
inner join table2 as t2
on t2.KodikosBarcode = t3.KodikosBarcode

Delete from TableA with Where equals in TableB

I have a staging table through which I want to delete all matching records in my Customers table. In "language terms":
delete
tableA.*
from
table A,table B
where
TableA.col1=TableB.col1
&& TableA.colb=TableB.col2 /// and so forth
Some info about the tables:
There are no relationships between the tables. The only true way to match the records is to match all of the columns (I want to clear any duplicates)
There are no foreign keys inplace between the 2 tables. Staging table is imported from CSV and the data will be transformed to use within our system.
Most of the imports will be identical (with around 80% of the staging rows to be deleted from around 60k records)
I have this working in Linq2SQL but it's taking a longer due to all of the queries and as there is around 80% matching records with each query and I feel a single query should be suffice.
Is this at all possible in SQL?
You can use JOIN with DELETE
DELETE a
FROM tableA a
INNER JOIN tableB b
ON a.Col1 = b.Col1
AND a.ColB = b.ColB
... and so on
or by using EXISTS:
DELETE a
FROM tableA a
WHERE EXISTS
(
SELECT 1 FROM tableB b
WHERE a.Col1 = b.Col1
AND a.ColB = b.ColB
....
)
merge table1 t1
using (
select t2.ID
from table2 t2
) as d
on t1.ID = d.ID
when matched then delete;

How to merge SQL Server data efficiently?

I have three tables in SQL Server where I need to combine all matching rows from all tables into a fourth MergedTable that will contain all the columns from the three individual tables based on the U_ID column.
Is there a way of doing this via T-SQL in a stored procedure, or should I just create a loop function in C#?
Bottom line is this is going to be executed from a command from a website, so it needs to be something I can encapsulate into an MVC project or component.
Here is an example of the tables.
Table 1:
U_ID ClientNumber OrderDate Amount
---------------------------------------------
BB000Kw 1920384 5/14/2013 1093.39
AA000bM 3839484 12/8/2012 584.42
AA000gH 8294848 2/28/2014 4849.38
AA000md 3849484 4/31/2013 590.84
AA000mF 3998398 3/29/2013 448.82
AA000mG 9944848 11/28/2014 98.85
AA000mn 0292938 10/31/2012 300.48
Table 2:
U_ID Name Date
------------------------------------------
AA000bM "Krivis, Jeffrey" 7/1/2002
AA000bv "Saydah, Michael" 7/30/2002
AA000cA "Byrne, Richard" 4/21/2003
AA000dd "McNeil, Joseph" 6/10/2003
AA000dH "Greenberg, Arnold" 1/16/2003
AA000gH "Rich, Elwood" 7/5/2003
AA000id "O'Neill, Robert J." 11/20/2002
AA000jf "Patsey, Richard" 4/22/2003
AA000jr "Jones, Arthur" 7/1/2002
AA000jU "Toff, Ronald" 7/15/2002
AA000k4 "Anderson, Carl" 8/14/2002
BB000Kw "Wilson, Sam" 3/9/2003
Table 3:
U_ID Name
-----------------------------
AA000bM Acme Company
AA000jr Stockwell Industries
BB000ke Gensen Motors
BB999di Falstaff Cards
BB000dl B and R Printing
BB000Kw Go Golf Carts
AA000gH Rich's Sandwiches
Resulting merged table
U_ID ClientNumber OrderDate Amount CustomerName JoinDate CompanyName
-------------------------------------------------------------------------------------------------------
BB000Kw 1920384 5/14/2013 1093.39 "Wilson, Sam" 3/9/2003 Go Golf Carts
AA000bM 3839484 12/8/2012 584.42 "Krivis, Jeffrey" 7/1/2002 Acme Company
AA000gH 8294848 2/28/2014 4849.38 "Rich, Elwood" 7/5/2003 Rich's Sandwiches
Table 1 is the master table that the others are matched to. You can see from the result that there will be only a subset of all the tables based on those that are matched from Table 1.
I'll be using MVC with the Entity Framework 6 and Linq-to-Entities, but if a T-SQL script is more efficient, then I should probably use that instead.
Which is the better way to go to get this result?
If you want to create a new table you can use SELECT ... INTO ... FROM ... query. In your case it would look like this:
SELECT t1.U_ID, t1.ClientNumber, t1.OrderDate, t1.Amount,
t2.Name as CustomerName, t2.Date as JoinDate,
t3.Name as CompanyName
INTO dbo.ResultingMergedTable
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.U_ID = t2.U_ID
INNER JOIN Table3 t3 ON t1.U_ID = t3.U_ID
Keep in mind that if you are looking at really big data table this will take a lot of time to execute.
You can create a 4th table to do what you mentioned but if you are using sql you can create a view to do the same thing. A view is a virtual table. We use this when we partition data as well as make a detailed record like described above.
http://msdn.microsoft.com/en-us/library/ms187956.aspx
http://www.sqlinfo.net/sqlserver/sql_server_VIEWS_the_basics.php
CREATE VIEW DetailView AS
(
SELECT
-- table1
t1.U_ID,
t1.ClientNumber,
t1.OrderDate,
t1.Amount,
-- table2
t2.Name,
t2.Date as [JoinDate],
-- table3
t3.Name as [Company]
FROM
table1 t1
LEFT JOIN
table2 t2
ON t1.U_ID = t2.U_ID
LEFT JOIN
table3 t3
ON t1.U_ID = t3.U_ID
WHERE
t1.U_ID = t2.U_ID
and
t1.U_ID = t3.U_ID
)

Find duplicates between two SQL tables

I have two tables (Table1 and Table2) with the same primary keys, lets say Key1 and Key2. What I need to do is seperate the records in Table1 into two groups, the duplicates (records found in Table2) and the non-duplicates. I know I could use the below, but that seems bloated and repetetive. Is there a trimmer way to do this, possibly with a single call?
SELECT Key1, Key2 FROM Table1 WHERE Key1 IN (SELECT Key1 FROM Table2) AND Key2 IN (SELECT Key2 FROM Table2);
SELECT Key1, Key2 FROM Table1 WHERE Key1 NOT IN (SELECT Key1 FROM Table2) AND Key2 NOT IN (SELECT Key2 FROM Table2);
;
This call is being made from a C# ASP.NET codebehind page.
This query does a left outer join to ensure all records from table1 are returned. It joins on Table2, and if there are no matches, than any columns in Table2 will be NULL for that row. This behavior is used in a CASE statement to set a flag telling where the Table1 row exists in Table2 or not:
select t1.*,
case when t2.Key1 is null then 'false' else 'true' end as IsDuplicate
from Table1 t1
left outer join Table2 t2 on t1.Key1 = t2.Key1
and t1.Key2 = t2.Key2
You can then filter in your application based on the IsDuplicate column.
Check the new upsert statement in SQL2008
Upsert in SQL2008

Categories