Data insertion into the hierarchy format from one table to another - c#

I have an issue in insertion of records from one table to another the tables schema is same
Table 1
Id Parent Id Text
11 Null A
12 Null B
13 11 C
14 11 D
15 13 E
The record should be inserted in this format, I have to copy the foreign key relation not the identities of it.
Table 2
Id Parent Id Text
31 Null A
32 Null B
33 31 C
34 31 D
35 33 E

What you want could be achieved easily in the Database side.
But since you are looking for a linq approach. Here is how it can be achieved.
The Process is divided into two parts:
Hoping that you would have the model for the Table1 and Table2 something like(use the order you think is helpful. For my thinking the Table1 is the temp table):
Public class myEntity
{
public int Id{get; set;}
public int? ParentId{get; set;}
public string Text{get; set;}
}
1st: Copying all the Text Properties from Table A and inserting them into Table B with incrementing the IDs
var Table2 = new List<myEntity>();
Table1.Select(s=>s.Text).OrderBy(o=>o).ToList().ForEach(f=>
{
//now append the texts to
Table2.Add(new tablesTest { Id = (Table2.Count + 1), Text = f });//remove the Id property manupulation or set it to 0 if you are inserting directly in the database and use the context.SaveChanges();(*if entity-framework*) once the insertion is complete.
}}
2nd: Creating a mapping table using self-join to get the parent-child relationship between the entries from Table1 and then updating the entries in Table2
var parentChildListFromTb1 = from m in Table1
join ch in Table1 on m.Id equals ch.ParentId
select new
{
Id = ch.Id,
Parent = m.Text,
Text = ch.Text
};
Which will give you an output:
----------------------------
| Id | Parent | Text |
----------------------------
| 13 | A | C |
----------------------------
| 14 | A | D |
----------------------------
| 15 | C | E |
----------------------------
Now after we have the parent-child list now we create the child list by querying Table2 and updating its ParentId with their respected Ids:
parentChildListFromTb1.ForEach(f=>{
var ChildEntity = Table2.Single(s => s.Text.Equals(f.Text));//fetching the child entity from Table2
ChildEntity.ParentId = Table2.Single(s => s.Text.Equals(f.Parent)).Id;//updating the parentIds in Table2
});
And the Table2 will look something like :
------------------------------
| Id | ParentId | Text |
------------------------------
| 1 | null | A |
------------------------------
| 2 | null | B |
------------------------------
| 3 | 1 | C |
------------------------------
| 4 | 1 | D |
------------------------------
| 5 | 3 | E |
------------------------------

I have found a solution to this question.
Steps:
Insert the Text column values into the main table, leaving the ParentId as null and at the same time insert the values into a Dictionary as oldId key and New Inserted Id as value to the corresponding key.
After insertion Update the values on the basis of the mapped Dictionary keyValue Pair

Related

How to delete some row in table1 and its change should reflect in table2 in C# using sql query?

Let us suppose I have two table namely Table1 and Table2.
Table1 contains:
+------+--------+
| Name | Value |
+------+--------+
| a | 5 |
| b | 10 |
| c | 5 |
| a | 20 |
| b | 15 |
+------+--------+
Table2 contains:
+------+--------+
| Name | Value |
+------+--------+
| a | 25 |
| b | 25 |
| c | 5 |
+------+--------+
My question is if i delete row 4 and row 5 in Table1 . The content of Table 2 should contain, somewhat like:
Table2:
+------+--------+
| Name | Value |
+------+--------+
| a | 5 |
| b | 10 |
| c | 5 |
+------+--------+
If you really want to store table2 as a table, then you would need a trigger. I would instead suggest that you use a view:
create view table1_summary as
select t1.name, sum(t1.value) as value
from table1 t1
group by t1.name;
Then the values are calculated when you access the view. Note: This will be slower if table1 is big.
Here is a trigger exemple which can do the work for you :
CREATE TRIGGER [dbo].[up_update_my_second_table]
ON [dbo].[Table1] FOR DELETE
AS
DECLARE #Name VARCHAR(50)
SELECT #Name = [Name] FROM deleted --deleted represents the deleted line.
UPDATE Table2 SET [Value] = 'YourValue' WHERE [Name] = #Name
You can use Triggers in SQL to delete from Second Table when you are trying to delete from First Table ..

Entity ORM Joining Two Tables Off ID ForeignKey given non-foreignkey?

I have a string, name.
I have two tables:
Table 1:
|---------------------|------------------|
| ID | PadName |
|---------------------|------------------|
| 12 | "Hello" |
|---------------------|------------------|
Table 2
|------------------------------------------|------------------|
| MetaDataID (FK to ID in table1) | .......... |
|------------------------------------------|------------------|
| 12 | Other Data..
|------------------------------------------|------------------|
Example Query:
Select ID from table1 given a padName the join that ID with table2.
I'm using entity framework in C# and what I want is to feed in a PadName in Table 1 and then get all the associated Table 2 data where the ID fields match (since table2 has an FK relationship to table 1).
I've seen some example code like the following:
var query = _context.PadMetaData
.Where(x => x.PadName == padName).Select(p => new { p.id });
Then I want to take that id result and join it with the MetaDataId in table2.
But I can't seem to achieve what I want.

MySQL query for search filter from multiple tables

I have multiple tables and i have a search ASP.NET page with a GridView for the results.
The GridView must contain Name, School, State, Country
I have multiple tables that only contains the data:
index_States
indexID| State
----------------
1 | state1
2 | state2
3 | state3
index_Contries
indexID| Country
----------------
1 | country1
2 | country2
3 | country3
index_Schools
indexID| School
----------------
1 | school1
2 | school2
3 | school3
Then i have the tables that contains the indexID as reference
General_Info
idKey | Name
--------------
1 | John
2 | McClane
3 | Jr.
Academic_XP
id | idSchool | idState | idCountry | idKey
--------------------------------------------
1 | 1 | 3 | 20 | 2
2 | 1 | 5 | 146 | 3
3 | 2 | 1 | 65 | 9
And THEN I have the table that contains UserType as only certain type of user will be searched
Users
id | UserType | idKey
-----------------------
1 | 1 | 1
2 | 3 | 2
3 | 3 | 3
4 | 1 | 4
I've already tried multiple queries but none seem to be working.
Last query that seem to be working was with INNER JOIN
SELECT Name, State
FROM General_Info A, Academic_XP B
INNER JOIN index_States D ON B.idState = D.indexID
GROUP BY A.id;
but it doesn't work as soon as I add a second INNER JOIN or a WHERE clause.
SELECT Name, State
FROM General_Info A, Academic_XP B, Users
INNER JOIN index_States D ON B.idState = D.indexID
INNER JOIN index_School E ON B.idSchool = E.indexID
GROUP BY A.id
WHERE Users.UserType = 3;
I don't know how can I do that.
So i guess the question is
How can I made a query that returns from all those tables something like this?
Name | State | School | Country
---------------------------------------
McClane | state3 | school1 | country20
Jr. | state1 | school5 | country146
Note that McClane and Jr. are both UserType 3.
I will appreciate any help.
You are producing a cartesian product between tables without joins. I think this is what you're looking for using additional JOINs:
SELECT DISTINCT
G.Name,
S.State,
C.Country,
SC.School
FROM Academic_XP A
JOIN Users U ON A.idKey = U.idKey
JOIN General_Info G ON A.id = G.idKey
JOIN Index_States S ON A.idState = S.indexID
JOIN Index_Contries C ON A.idCountry = C.indexID
JOIN Index_Schools SC ON A.idSchool = SC.indexID
WHERE U.UserType = 3
If some tables don't have matching keys, you'll need to use an OUTER JOIN.
A Visual Explanation of SQL Joins

Query tabels to sort sums across rows and count based on a value in LINQ

Here is my problem. i have 3-5 persons that is going to set a grade on one person and they use their own individual row to do so, and what I'm having trouble to do is to sum and average the grade from individual data across multiple rows on the same table.
in the select new statement i have made a pseudo answer of what i want
var users = from workRew in db.Reviews
select new
{
UserID = workRew.UserID.DistinctOfSomeSort
AvgGrade = workRew.Grade.Sum/CountOfSomeSort
};
Here i a illustration.
So if i have this table
| SomeID | UserID | Grade |
| 1 | 2 | 3 |
| 2 | 3 | 1 |
| 3 | 2 | 1 |
And this is the output i want from the LINQ query on the above (In theory ateast)
| UserID | AvgGrade |
| 2 | 2 |
| 3 | 1 |
EDIT: Simplified the whole case, to a great extent.
It should look something like this fragment:
group by user.UserID
select new
{
User = user.UserID
TotGradeCount = workRew.Grade.Sum()
Graders = workRew.Grade.Count()
}

Version Control Algorithm

I have a database where I store objects. I have the following (simplified) schema
CREATE TABLE MyObjects
(
UniqueIdentifier Id;
BigInt GenerationId;
BigInt Value;
Bit DeleteAction;
)
Each object has a unique identifier ("Id"), and a (set of) property ("Value"). Each time the value of the property for an object is changed, I enter a new row into this table with a new generation id ("GenerationId", which is monotonically increasing). If an object is deleted, then I record this fact by setting the "DeleteAction" bit to true.
At any point in time (generation), I would like to retrieve the state of all of my active objects!
Here's an example:
Id GenerationId Value DeleteAction
1 1 99 false
2 1 88 false
1 2 77 false
2 3 88 true
Objects in generations are:
1: 1 {99}, 2 {88}
2: 1 {77}, 2 {88}
3: 1 {77}
The key is: how can I find out the row for each unique object who's generation id is closest (but not exceeding) to a given generation id? I can then do a post-filter step to remove all rows where the DeleteAction field is true.
This works in MS SQL
SELECT id,value
FROM Myobjects
INNER JOIN (
SELECT id, max(GenerationID) as LastGen
FROM MyObjects
WHERE GenerationID <= #Wantedgeneration
Group by ID)
On GenerationID = LastGen
WHERE DelectedAction = false
My version uses a joint of the table MyObjects against a
subset of itself, created by a subquery, and containing only the last
generation for each object:
SELECT O.id,generation,value FROM
MyObjects O,
(SELECT id,max(generation) AS max_generation FROM MyObjects
WHERE generation <= $GENERATION_ID GROUP BY id) AS TheMax WHERE
TheMax.max_generation = generation AND O.deleted is False
ORDER BY generation DESC;
In the above query, the GENERATION_ID is hardwired. A way to
parametrize it is to write a function:
CREATE OR REPLACE FUNCTION generation_objects(INTEGER) RETURNS SETOF MyObjects AS
'SELECT O.id,generation,value,deleted FROM
MyObjects O,
(SELECT id,max(generation) AS max_generation FROM MyObjects
WHERE generation <= $1 GROUP BY id) AS TheMax WHERE
TheMax.max_generation = generation AND O.deleted is False;'
LANGUAGE SQL;
Now, it works. With this table:
> SELECT * FROM MyObjects;
id | generation | value | deleted
----+------------+-------+---------
1 | 1 | 99 | f
2 | 2 | 88 | f
1 | 3 | 77 | f
2 | 4 | 88 | t
3 | 5 | 33 | f
4 | 6 | 22 | f
3 | 7 | 11 | f
2 | 8 | 11 | f
I get:
> SELECT * FROM generation_objects(1) ORDER by generation DESC;
id | generation | value | deleted
----+------------+-------+---------
1 | 1 | 99 | f
> SELECT * FROM generation_objects(2) ORDER by generation DESC;
id | generation | value | deleted
----+------------+-------+---------
2 | 2 | 88 | f
1 | 1 | 99 | f
> SELECT * FROM generation_objects(3) ORDER by generation DESC;
id | generation | value | deleted
----+------------+-------+---------
1 | 3 | 77 | f
2 | 2 | 88 | f
And then, at the following generation, object 2 is deleted:
> SELECT * FROM generation_objects(4) ORDER by generation DESC;
id | generation | value | deleted
----+------------+-------+---------
1 | 3 | 77 | f
Here's the working version:
SELECT MyObjects.Id,Value
FROM Myobjects
INNER JOIN
(
SELECT Id, max(GenerationId) as LastGen
FROM MyObjects
WHERE GenerationId <= #TargetGeneration
Group by Id
) T1
ON MyObjects.Id = T1.Id AND MyObjects.GenerationId = LastGen
WHERE DeleteAction = 'False'
Not sure whether that's standard SQL, but in Postgres, you can use the LIMIT flag:
select GenerationId,Value,DeleteAction from MyObjects
where Id=1 and GenerationId < 3
order by GenerationId
limit 1;

Categories

Resources