i have 3 tables mainCategory, subCategory and products.i want to update main category but by the time it should update the respected data in other remaining tables too.following ar my tables.
1. mainCategory
mainCatId
mainCatName
2. subCategory
subCatId
mainCatId
mainCatName
subCatName
3. products
productId
subCatId
subCatName
productName
update has to be like,when i change mainCatName it automaticaly changes mainCatId,so it should be change mainCaId and mainCatName,subCatId and subCatName in other tables too, i have tried a query but its not working
query is:
UPDATE mainCategory
SET mainCatId =, mainCatName =
FROM mainCategory
INNER JOIN
subCategory ON mainCategory.mainCatId = subCategory.mainCatId
CROSS JOIN
products
,kindly help me out!
You need to link your tables with a Foreign Keys and apply ON UPDATE CASCADE in table definition.
You do not need to have mainCatName in subCategory table, because subCategory table should be linked with a foreign key with a mainCategory table.
Same thing with a subCatgoryName in products table.
CREATE TABLE mainCategory (
[mainCatId] INT NOT NULL,
[mainCatName] NCHAR (10) NULL,
PRIMARY KEY CLUSTERED ([mainCatId] ASC));
CREATE TABLE subCategory (
[subCatId] INT NOT NULL,
[mainCatId] INT NULL,
[subCatName] NCHAR (10) NULL,
PRIMARY KEY CLUSTERED ([subCatId] ASC),
CONSTRAINT [FK_Table_ToTableMainCat] FOREIGN KEY ([mainCatId])
REFERENCES [mainCategory] ([mainCatId]) ON UPDATE CASCADE);
CREATE TABLE products (
[productId] INT NOT NULL PRIMARY KEY,
[subCatId] INT NULL,
[productName] NCHAR(10) NULL,
CONSTRAINT [FK_products_ToTableSubCategory] FOREIGN KEY (subCatId)
REFERENCES subCategory(subCatId) ON UPDATE CASCADE);
You can update mainCatName simply by:
UPDATE mainCategory SET mainCatName='NEW NAME' WHERE mainCatId=SOMEID;
Your subCategory table linked with a mainCategory table through a FOREIGN KEY.
Your products table linked with a subCategory table with a FOREIGN KEY.
If you want to get the products of the particular mainCategory:
SELECT productName, subCatName, mainCatName FROM products
JOIN subCategory ON products.subCatID = subCategory.subCatID
JOIN mainCategory ON subCategory.mainCatID = mainCategory.mainCatID
where mainCategory.mainCatID = 1;
If you want to get the products of the particular subCategory:
SELECT productName, subCatName FROM products
JOIN subCategory ON products.subCatID = subCategory.subCatID
where subCategory.subCatID = 1;
If you want to delete the products from a particular subCategory, you just delete the subcategory record and corresponding products will be deleted on cascade.
If you want to change the Name of the subCategory, you just change the record in the subCategory table.
Related
When you have two tables with a foreign key for example
CREATE TABLE departments
( department_id INTEGER PRIMARY KEY AUTOINCREMENT,
department_name VARCHAR
);
CREATE TABLE employees
( employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
last_name VARCHAR NOT NULL,
first_name VARCHAR,
department_id INTEGER,
CONSTRAINT fk_departments
FOREIGN KEY (department_id)
REFERENCES departments(department_id)
);
Then when you insert data like this:
INSERT INTO departments VALUES (30, 'HR');
INSERT INTO departments VALUES (999, 'Sales');
INSERT INTO employees VALUES (10000, 'Smith', 'John', 30);
INSERT INTO employees VALUES (10001, 'Anderson', 'Dave', 999);
What is the best way of finding the values 30 and 999 when inserting into the emplyees table?
Here is an example using the sqlite last_insert_id() function (I'm going to clean this up to show that it really is an auto-number value, rather than a department number you already know):
begin transaction;
insert into departments (department_name) values ('HR');
insert into employees values (10000, 'Smith','John',last_insert_rowid());
insert into departments (department_name) values ('Sales');
insert into employees values (10001, 'Anderson','Dave',last_insert_rowid());
commit;
Another strategy is to use your departments names, so you can avoid worrying about knowing the ids at all (I will assume you add a unique constraint so that department names must be unique - which is sensible):
insert into departments values (30, 'HR');
insert into departments values (999, 'Sales');
insert into employees
select
10000,
'Smith',
'John',
(select department_id
from departments
where department_name = 'HR');
insert into employees
select
10001,
'Anderson',
'Dave',
(select department_id
from departments where department_name = 'Sales');
In my database, I created the tables structure as follows.
CREATE TABLE Course
(
Course_ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(255) NOT NULL,
);
CREATE TABLE Student
(
Stu_ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(255) NOT NULL,
Mobile varchar(255),
Age int,
Course_ID int,
FOREIGN KEY (Course_ID) REFERENCES Course(Course_ID)
);
CREATE TABLE Subject
(
Sub_ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(255) NOT NULL,
);
CREATE TABLE Teacher
(
Teach_ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(255) NOT NULL,
Mobile varchar(255)
);
CREATE TABLE Course_Subject
(
CouSub_ID int IDENTITY(1,1) PRIMARY KEY,
Course_ID int,
Sub_ID int,
FOREIGN KEY (Course_ID) REFERENCES Course(Course_ID),
FOREIGN KEY (Sub_ID) REFERENCES Subject(Sub_ID)
);
CREATE TABLE Teacher_Subject
(
TeachSub_ID int IDENTITY(1,1) PRIMARY KEY,
Teach_ID int,
Sub_ID int,
FOREIGN KEY (Teach_ID) REFERENCES Teacher(Teach_ID),
FOREIGN KEY (Sub_ID) REFERENCES Subject(Sub_ID)
);
Now my problem is I need to retrieve students data who learned from some teacher, which means need to retrieve some teacher's students who learned from his/her. To accomplish my requirement. I write this SQL query.
select
s.*
from
tbl_student s
inner join
Course_Subject tcs on s.Course_Id = tcs.Course_Id
inner join
Teacher_Subject tst on tst.Sub_ID = tcs.Sub_ID
inner join
Teacher t on t.Teach_ID = tst.Teach_ID
where
t.Teach_ID = #SomeTeacherId
Now I need to convert this query to a lambda expression or Linq. How can I do it? Please help me. Have any possible way to generate this using Visual Studio.
Well, you could use EF to generate object mapping to your tables. And use LINQ to rewrite your query with a slightly different syntax:
var result = from students in tbl_student
join subjects in Course_Subject on students.Course_Id == subjects.Course_Id
join ts in Teacher_Subject on subjects.Sub_ID == ts.Sub_ID
join teachers in Teacher on teachers.Teach_ID == ts.Teach_ID
where teachers.Teach_ID == "your_value"
select students;
Not sure it's an absolutely correct query, but I hope you'll get the main idea.
Have any possible way to generate this using Visual Studio.?
Yes, you can do this using Linq-to-SQL
for your query, this might be appropriated
var students = from student in db.Students
join tcs in db.CourseSubjects on student.CourseId equals tcs.CourseId
join tst in db.TeacherSubjects on tcs.SubId equals tst.SubId
join t in db.Teachers on tst.TeachId equals t.TeachId
where t.TeachId == someTeacherId
select student;
Lambda:
Students
.Where(x=> x.Course.Course_Subjects
.Any(y => y.Subject.Teacher_Subjects
.Any(z => z.Teach_ID == someTeacherId)
)
)
.Select(x => x)
I am joining two tables using primary key and foreign key.
My tables are
Item, Columns are:
ItemId int primary key,
Name varchar,
Price float,
CategoryID int foreign key,
QtyInStock int
Category, Columns are:
Id int pk,
Category varchar,
Name varchar
I want to select Category on basis of ID=categoryId
I am using NHibernate 4.03 with xml configuration files.
For unrelated entities:
var query = from item in session.Query<Item>()
join category in session.Query<Category>() on item.CategoryID equals category.Id;
For related entities:
Category catAlias = null;
var query = session.QueryOver<Item>()
.JoinAlias(x => x.Category, () => catAlias);
SELECT it.uid,it.Name,COALESCE(sum(i.Qty),0)-COALESCE(sum(s.Qty),0) as stock
FROM items it
left outer join sales_items s on it.uid=s.ItemID
left outer join inventory i on it.uid=i.uid
group by s.ItemID,i.uid,it.UID;
This is my query. This query take 59 seconds. How can I speed up this query?
my tables ->
items
UID Item
5089 JAM100GMXDFRUT
5090 JAM200GMXDFRUT
5091 JAM500GMXDFRUT
5092 JAM800GMXDFRUT
tables ->
sales_items
- slno ItemID Item Qty
- 9 5089 JAM100GMXDFRUT 5
- 10 5090 JAM200GMXDFRUT 2
- 11 5091 JAM500GMXDFRUT 1
tables ->
inventory
- slno uid Itemname Qty
- 102 5089 JAM100GMXDFRUT 10
- 200 5091 JAM500GMXDFRUT 15
- 205 5092 JAM800GMXDFRUT 20
This table has more than 6000 rows
Put indexes on the join columns
sales_items ItemID
inventory uid
If I was designing something like this I would have a query and schema that looks like this. Take note of my Idx1 indexes. I don't know about MySql but Sql Server will make use of those indexes for the sum function and this is called a covered query.
select Item.ItemID, Item.Name, IsNull(sum(inv.Quantity), 0) - IsNull(sum(s.Quantity), 0) as stock
from Item
Left Join Inventory inv
On Item.ItemID = inv.ItemID
Left Join Sales s
On Item.ItemID = s.ItemID
Group by Item.ItemID, Item.Name
Create Table dbo.Location
(
LocationID int not null identity constraint LocationPK primary key,
Name NVarChar(256) not null
)
Create Table dbo.Item
(
ItemID int not null identity constraint ItemPK primary key,
Name NVarChar(256) not null
);
Create Table dbo.Inventory
(
InventoryID int not null identity constraint InventoryPK primary key,
LocationID int not null constraint InventoryLocationFK references dbo.Location(LocationID),
ItemID int not null constraint InventoryItemFK references dbo.Item(ItemID),
Quantity int not null,
Constraint AK1 Unique(LocationID, ItemID)
);
Create Index InventoryIDX1 on dbo.Inventory(ItemID, Quantity);
Create Table dbo.Sales
(
SaleID int not null identity constraint SalesPK primary key,
ItemID int not null constraint SalesItemFK references dbo.Item(ItemID),
Quantity int not null
);
Create Index SalesIDX1 on dbo.Sales(ItemID, Quantity);
Aside from indexes on the tables to optimize joins, you are also doing a group by of the S.ItemID instead of just using the IT.UID since that is the join basis, and part of the main FROM table of the query... if that is an available index on the items table, use that and you are done. No need to reference the sales_items or inventory column names in the group by.
Now, that being said, another problem you will run into the way you have it is a Cartesian result if you have more than one record for the same "item id" you are summing from sales_items and inventory as I have extremely simplified an example for you via
CREATE TABLE items (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(5) NOT NULL,
PRIMARY KEY (`uid`)
);
CREATE TABLE sales_items (
`sid` int(11) NOT NULL AUTO_INCREMENT,
`itemid` int(11),
`qty` int(5) NOT NULL,
PRIMARY KEY (`sid`),
KEY byItemAndQty (`itemid`,`qty`)
);
CREATE TABLE inventory (
`iid` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`qty` int(5) NOT NULL,
PRIMARY KEY (`iid`),
KEY byItemAndQty (`itemid`,`qty`)
);
insert into items ( uid, name ) values ( 1, 'test' );
INSERT INTO sales_items ( sid, itemid, qty ) VALUES ( 1, 1, 1 );
INSERT INTO sales_items ( sid, itemid, qty ) VALUES ( 2, 1, 2 );
INSERT INTO inventory ( iid, uid, qty ) VALUES ( 1, 1, 13 );
INSERT INTO inventory ( iid, uid, qty ) VALUES ( 2, 1, 35 );
Simple 1 item,
Sales items 2 records for Item 1.. Qty of 1 and 2, total = 3
Inventory 2 records for Item 1.. Qty of 13 and 35, total 38
SELECT
it.uid,
it.Name,
sum(i.Qty) as iQty,
sum(s.Qty) as sQty,
COALESCE( sum(i.Qty),0) - COALESCE(sum(s.Qty),0) as stock
FROM
items it
left outer join sales_items s
on it.uid = s.ItemID
left outer join inventory i
on it.uid = i.uid
group by
it.uid
So, the result of the query you MIGHT EXPECT the Stock to be
uid name iQty sQty stock
1 test 48 3 45
but in reality becomes
1 test 96 6 90
NOW... PLEASE TAKE NOTE OF MY ASSUMPTION, but see similar sum()s or count()s from multiple tables like this. I am assuming the ITEMS table is one record per item.
The Sales_Items actually has more columns than provided (such as sales details and every date/sales count could be tracked) and MAY CONTAIN Multiple sales record quantities for a given item id (thus matching my sample).. Finally, the Inventory table similarly could have more than one record per same item, such as purchases of incoming inventory tracked by date and thus multiple records per a given item id (also matching my example).
To prevent this type of Cartesian result, and can also increase speed, I would do pre-aggregates per secondary table and join to that.
SELECT
it.uid,
it.Name,
i.iQty,
s.sQty,
COALESCE( i.iQty,0) - COALESCE(s.sQty,0) as stock
FROM
items it
left join ( select itemid, sum( qty ) as SQty
from sales_items
group by itemid ) s
on it.uid = s.ItemID
left join ( select uid, sum( qty ) as IQty
from inventory
group by uid ) i
on it.uid = i.uid
group by
it.uid
And you get the correct values of
uid name iQty sQty stock
1 test 48 3 45
Yes, this was only for a single item ID to prove the point, but still applies to as many inventory items as you have and respective sales/inventory records that may (or not) exist for certain items.
I am trying to get a single property from a joined table where a non-PK in my main table is joined to the PK of the foreign table. Below is an oversimplified example of what I am trying to accomplish (I do not want to reference the foreign entity):
Tables:
CREATE TABLE Status
(
Id int,
Body text,
CategoryId int
)
CREATE TABLE Category
(
Id int,
Name text
)
SQL to generate:
SELECT Id, Body, CategoryId, Category.Name AS CategoryName
FROM Status
LEFT JOIN Category ON Category.Id = Status.CategoryId
I am trying to map the join like this in the StatusMap but it seems to be joining on the two primary keys (where Status.Id = Category.Id):
Join("Category" m =>
{
m.Optional();
m.KeyColumn("CategoryId");
m.Map(x => x.CategoryName, "Name");
});
As far as I know the only way around this using Fluent is to map to a view as you currently are doing. Join() will always map to the primary key of the parent table. The KeyColumn method specifies the key column for the child table only, which in your case is the Category table.
To achieve the desired SQL using your simplified version above you'd probably want to use References to define a many-to-one relationship between status and category.