I had an index working really nicely last night, low I/O all that good stuff. Now this morning I added a primary key to the table and the performance has dropped and the optimizer ignores the index even with hints.. Any advice? Thankyou
Schema structure..
Product
ID PK
Name
Price
Order_Line
Order_ID FK
Product_ID FK
Qty
Orders
ID PK
O_Date date
CustID
Query...
SELECT SUM(OL.QTY) FROM PRODUCT P,ORDERS O, ORDER_LINE OL
WHERE
P.NAME = 'APRICOT JAM'
AND
P.ID = OL.PRODUCT_ID
AND
O.O_DATE = '03-MAR-2014'
AND
OL.ORDER_ID= O.ID
;
The index which it isn't using is a composite index on product which is (name,ID), instead its using products primary key to do an index range scan Thanks!
Product Table
ID PK
Name INDEX01
Price
I would structure your table this way.
Your query is going to range scan because it is going to scan the table for the P.NAME = 'APRICOT JAM' clause in your query.
Related
I want to create three tables.
Orders (contains an order ID and a customer name)
Products (contains a Product ID, description, and price)
Line Item (contains Order ID, Line Item ID, Product ID, and Quantity)
I want my web app to allow a customer to select an order number, and as a result, it will display the products that are in that order, the quantity of said products, the price of the products, and a total price of order that will be calculated on the fly in my code behind.
My SQL looks like this
CREATE TABLE Products
(
ProductID int NOT NULL,
ProductDescription varchar(MAX) NOT NULL,
ProductPrice smallmoney NOT NULL,
PRIMARY KEY (ProductID)
)
CREATE TABLE Orders(
OrderID int NOT NULL,
CustomerName varchar(MAX) NOT NULL,
PRIMARY KEY (OrderID)
)
CREATE TABLE LineItem(
LineItemID int NOT NULL,
OrderID int NOT NULL FOREIGN KEY REFERENCES Orders(OrderID),
ProductID int NOT NULL FOREIGN KEY REFERENCES Products(ProductID),
Quantity int NOT NULL,
PRIMARY KEY (LineItemID)
)
Here is the database diagram with the relationships.
Here is the result of a select all statement on all the tables
Are my relationships set up correctly for what I want to achieve? I'm sorry if this seems simple but I'm new to this and while the SQL Statements are pretty easy, the way to relate tables is not.
SELECT p.ProductPrice, p.ProductDescription, o.CustomerName, l.Quantity
FROM LineItem AS l
INNER JOIN Products AS p ON l.ProductID=p.ProductID
INNER JOIN Orders AS o ON l.OrderID=o.OrderID
ORDER BY l.LineItemID
will provide combined information from all of these tables. You may add any additional columns which you want to fetch data from.
INNER JOIN and JOIN keywords are syntactic sugar, which have same effect. While you're binding two tables by INNER JOIN, only results which contained in both of these tables will be returned.
With the ON keyword, you are defining the relational columns of tables. For example, in the clause INNER JOIN Products AS p ON l.ProductID=p.ProductID, I'm defining that the data are relational in column ProductID of table Products with column ProductID of table LineItem.
You have a many-to-many relationship between Products and Orders so in the structure of LineItem table I think you already have have the primary key (Product Id,OrderID) and I think you do not need to LocalItemID
CREATE TABLE LineItem(
OrderID int NOT NULL FOREIGN KEY REFERENCES Orders(OrderID),
ProductID int NOT NULL FOREIGN KEY REFERENCES Products(ProductID),
Quantity int NOT NULL,
PRIMARY KEY (OrderID ,ProductID )
)
and you can join the tables using this:
SELECT p.ProductPrice, o.CustomerName, li.Quantity
FROM LineItem AS li
JOIN Products AS p ON li.ProductID=p.ProductID
JOIN Orders ON li.OrderID=o.OrderID
Scenario for my database design is as follows: people visit matchmakers who network with each other and propose matches. For example, person A visits matchmaker X, and person B visits matchmaker Y, where A not equals B and no constraint on X, Y i.e. they can be the same or different.
create table matchmaker ( id TEXT primary key, address TEXT );
create table people ( id TEXT primary key, name TEXT, gender TEXT, matchmaker_id TEXT,
foreign key(matchmaker_id) references matchmaker(id));
create table married_couples ( id1 TEXT, id2 TEXT,
foreign key (id1) references people(id),
foreign key (id2) reference people(id));
Then, for faster database access:
create index matchmaker_index on matchmaker(id);
create index people_index on people(id);
My question is based on the following query to generate tuples of matchmaker pairs with people they've paired.
select a.id, b.id, e.id1, e.id2
from matchmaker as a, matchmaker as b,
people as c, people as d,
married_couples as e
where e.id1 = c.id and c.id = a.id and
e.id2 = d.id and d.id = b.id;
For the query above, will the two matchmaker_index and people_index suffice or,
is there a need for two more (other) indexes as below?
create index matchmaker_people_index on people(id, matchmaker_id);
create index married_couples_index on married_couples(id1, id2);
additional info:
1) matchmaker has 20074 unique entries;
2) people has 20494819 unique entries;
3) married_couples ?? (i don't have this information yet, but it's going to be big)
Also, it's possible that married_couples will have duplicate entries. So,
after creating the relevant indexes, will run query to delete duplicates as below:
delete from married_couples
where rowid not in ( select min(rowid)
from married_couples
group by id1, id2);
SQLite generates indexes automatically for columns declared primary key or unique. FAQ, see question 7. So these two indexes
create index matchmaker_index on matchmaker(id);
create index people_index on people(id);
are duplicates. Drop them.
This index
create index matchmaker_people_index on people(id, matchmaker_id);
might help.
Also, it's possible that married_couples will have duplicate entries.
Remove that possibility. Add a primary key and a CHECK constraint.
create table married_couples (
id1 TEXT, id2 TEXT,
foreign key (id1) references people(id),
foreign key (id2) references people(id),
primary key (id1, id2),
check (id1 < id2)
);
The primary key provides an index, too.
When you're talking about marriages, a marriage between Mike and Mindy is a duplicate of a marriage between Mindy and Mike. The CHECK constraint prevents that kind of subtle duplication. It also prevents people from marrying themselves.
I'm not sure what you might want to do about the woman who married the Eiffel Tower.
You can simplify the original query quite a lot. Learning ANSI joins is a good idea.
select id1, id2, c.matchmaker_id m_id1, d.matchmaker_id m_id2
from married_couples a
inner join people c
on c.id = a.id1
inner join people d
on d.id = a.id1;
I have a table that contains all products. There are 3 distinct types of products so these have their own tables, lets say ProductType1, ProductType2, ProductType3.
There is a 1-1 relationship between Products and ProductType(n) on ProductId, but to further constraint the child tables there is an additional relationship using a ProductId, ProductTypeId in Products, and a ProductId, ComputedProductTypeId in each of the other tables.
This ensures that a product can only be added to a single matching ProductType table.
The question is this. As there is already a relationship between the 2 tables on ProductId, rather than using an index for the FK, can I get away with a unique key to constrain the relationship, or will this cause performance issues?
Products
PK ProductId
FK ProductId, ProductTypeId
^
*Add an index for this or unique key constraint?*
ProductType(n)
PK ProductId
FK ProductID, ComputedProductTypeId (fixed int)
Creating an index will be better approach.
If you want to delete entries from your master table, SQL server looks for FK relations if any exists. So Creating Index on your composite key (which includes FK) will speed up the process.
When you buy things online, you add them to your basket and when you've done adding things to your basket, you create an order. Essentially, I am trying to think of the best way to allow multiple items to be put into one order. This is more a case of not knowing how to store the data in a database in Access. I can't figure out what the fields should be called. My current attempt is this:
tblOrders
OrderID (Primary Key)
CustomerID (Foreign Key)
OrderDetailsID
tblOrderDetails
OrderDetailsID
PartID (Foreign Key)
Quantity
This is an image of the first table with example data and this is an example of the second table. It's very likely that I've missed something blindingly obvious.
Thankyou in advance.
I'd structure it like this:
OrderHeader
ID (Primary Key)
CustomerID (Foreign Key)
OrderDetail
ID (Primary Key)
OrderHeaderID (Foreign Key)
PartID (Foreign Key)
Quantity
Read up on Hungarian Notation as a naming convention, and consider dropping your tbl prefixes. This is just a preference you may choose to ignore.
OrderDetailID on the OrderHeader won't work because you won't be able to produce the necessary 1:M relationship where an order can have multiple detail lines.
Use surrogate ID fields for your primary keys. They make working with JOIN a lot easier. If you want to enforce a condition that an order can only use a part once, then you should do so with a unique database constraint on columns OrderHeaderID and PartID.
Here's a sample query for your comment...
SELECT H.ID OrderID, D.PartID, D.Quantity
FROM OrderHeader AS H INNER JOIN
OrderDetail AS D ON H.ID = D.OrderHeaderID
WHERE H.ID = 1234;
I want to store multiple translations of an text in a MSSQL database.
for example one table product with the columns
ProductId
ProductPrice
ProductNameId
primairy key = ProductId
and a table with the productnames
Id
Language
Name
primairy key = Id and Language
How can i create an foreign key to link the Product.ProductNameId to ProductName.Id
I think that the most appropriate pk-fk relationship is between ProductId on the Product table, and a ProductId (without Language) in the ProductName table. The field on the Product table is the pk, and the field in the ProductName table is the fk. That will ensure that there are no records in the PeoductName table that don't match with a record in the ProductName table.
If you want to treat Language similarly, then you can create a Language table with a LanguageId field. then, make a LanguageId field in the ProductNames table, and make that a fk.
when you retrieve product information, you JOIN Product and ProductName on their ProductId fields, and then specify the LanguageId in the WHERE clause.
I'd change the ProductNames table to:
Id
ProductId
Language
Name
With these constraints:
Primary key on Id
Foreign key on ProductId
Unique constraint on (ProductId,Language)