I have two tables in one database (access file).
Table 1:
| Product Id | Year | Sales |
----------------------------------
| 1144 | 2013 | 100 |
| 20131120 | 2013 | 200 |
| 1144 | 2012 | 333 |
Table 2:
| Product Id | Category |
----------------------------------
| 1144 | Car |
| 20131120 | Motorbike |
The first table (table 1) is the table when user can add new data whenever wants, and the second table is updated once in a while, when new product id appears. I would like to join this table, some kind of relation on the base of Product Id, but I'm not able to use relation due to the lack of unique, primary key, am I right? When I execute SQL query ( SELECT * FROM Table 1) I would like to get the result like this one:
| Product Id | Year | Sales | Category |
-----------------------------------------------
| 1144 | 2013 | 100 | Car |
| 20131120 | 2013 | 200 | Motrobike |
| 1144 | 2012 | 333 | Car |
I know I can join this two tables, but I would like not to do it every time when user add new data to table 1. Do you know any solution how could I do that?
I'm not able to use relation due to the lack of unique, primery key,
am I right?
No, this is not right, you can normally JOIN the two tables. It’s also legal to JOIN two tables or result sets on any columns that have what so called eligible data types.
SELECT
t1.ProductId, t1.year, t1.sales, t2.category
FROM table1 AS t1
INNER JOIN table2 AS t2 ON t1.productId = t2.productId;
but I would like not to do it every time when user add new data to
table 1
You don't need a ProductId in the second table, you need a CategoryId instead, and add a new column CategoryId to the first table too and declare it as a foreign key. Your tables should look like so:
Table1 (Products):
ProductId,
CategoryId,
Year,
Sales.
Table2 (Categories):
CategoryId,
CategoryName.
Then the category is added once to the categories table table2 and the product is added once to the products table table1. And for each product enter a CategoryId for it. This what so called normalization
You should also define ProductId in table1 and CategoryID in table2 as primary keys, and CategoryID in the first table as foreign key.
Related
I have a table Table_1 which has a list of SKU:
| SKU |
| R001 |
| R002 |
| R003 |
I then have a second table Table_2 which contains a list of sites:
| Site |
| Store1 |
| Store2 |
| Store3 |
I'd like to combine these tables so that each SKU exists at each Site.
So far I have the following:
SELECT
[Table_1].[SKU],
[Table_2].[Site]
FROM
[Table_1]
FULL OUTER JOIN
[Table_2] ON [Table_1].[SKU] = [Table_2].[Site]
This keeps on producing an error message based on conversion attempting to convert a SKU from type Varchar to Int.
Any advice or guidance on how to do this would be great please.
Thanks
This will bring each possible pair using both tables.
select * from table1 cross join table2
I want to get all rows in a table where one column matches a relationship with the value of the column in the row in a different table that has the same value of another column.
Concretely, I have two tables, orders and product_info that I'm accessing through Amazon Redshift
Orders
| ID | Date | Amount | Region |
=====================================
| 1 | 2019/4/1 | $120 | A |
| 1 | 2019/4/4 | $100 | A |
| 2 | 2019/4/2 | $50 | A |
| 3 | 2019/4/6 | $70 | B |
The partition keys of order are region and date.
Product Information
| ID | Release Date | Region |
| ---- | ------------ | ------ |
| 1 | 2019/4/2 | A |
| 2 | 2019/4/3 | A |
| 3 | 2019/4/5 | B |
The primary key of product information is id, and the partition key is region.
I want to get all rows from Orders in region A where the date of the row is greater than the release date value in product information for that ID.
So in this case it should return just one row,
| 1 | 2019/4/4 | $100 | A |
I tried doing
select *
from orders
INNER JOIN product_info ON orders.date>product_info.release_date
AND orders.id=product_info.id
AND orders.region=A
AND product_info.region=A
limit 10
The problem is that this query was absurdly slow (cancelled it after 10 minutes). The tables are extremely large, and I have a feeling it was scanning the entire table without restricting it to region first (in reality I have other filters in addition to region that I want to apply to the list of IDs before I do the inner join, but I've limited it to only region for the sake of simplifying the question).
How can I efficiently write this type of query?
The best way to make an SQL query faster is to exclude rows as soon as possible.
So, rather than putting conditions like orders.region=A in the JOIN statement, you should move them to a WHERE statement. This will eliminate rows before they are joined.
Also, make the JOIN condition as simple as possible so that the database can optimize the comparison.
Try something like this:
SELECT *
FROM orders
INNER JOIN product_info ON orders.id = product_info.id
WHERE orders.region = 'A'
AND product_info.region = 'A'
AND orders.date > product_info.release_date
Any further optimization would require consideration of the DISTKEY and SORTKEY on the Redshift tables. (Preferably a DISTKEY of id and a SORTKEY of date).
I have a database in which there are two tables tableA, tableB. Now for each primary id in tableA there may be multiple rows in tableB.
Table A primary key (ServiceOrderId)
+----------------+-------+-------+-------------+
| ServiceOrderId | Tax | Total | OrderNumber |
+----------------+-------+-------+-------------+
| 12 | 45.00 | 347 | 1011 |
+----------------+-------+-------+-------------+
Table B foreign key (ServiceOrderId)
+----+-------------+---------------------+----------+-------+------+----------------+
| Id | ServiceName | ServiceDescription | Quantity | Price | Cost | ServiceOrderId |
+----+-------------+---------------------+----------+-------+------+----------------+
| 39 | MIN-C | Commercial Pretreat | NULL | 225 | 23 | 12 |
+----+-------------+---------------------+----------+-------+------+----------------+
| 40 | MIN-C | Commercial Pretreat | NULL | 225 | 25 | 12 |
+----+-------------+---------------------+----------+-------+------+----------------+
Is there a way in which I can fetch the values as an array of multiple rows of tableB with single row of tableA. Because when I am saving to database I am using temp table to save multiple rows of tableB with single row of tableA.
Query I am using
SELECT
ordr.*,
info.*
FROM
tblServiceOrder as ordr
JOIN
tblServiceOrderInfo as info ON ordr.ServiceOrderId = info.ServiceOrderId
But above query is giving two rows for each ServiceOrderId. I am using node api to fetch data. I want something like;
Object:{
objectA:{id:12,tax:45.00:total:347,ordernumber:1011},
objectB:[
{id:39,servicename:'MIN-C',description:'Commercial Pretreat',Quantity :NULL,Price:225,Cost:23,ServiceOrderId:12 },
{id:40,servicename:'MIN-C',description:'Commercial Pretreat',Quantity :NULL,Price:225,Cost:25,ServiceOrderId:12}
]
}
There are several solutions. The first one is to use your SELECT, but with adding ORDER BY ServiceOrderID and when data are converting to object, to use the first row only in the loop for new ServiceOrderId from ordr table and add every row for the data from info table.
Other possibility is to select data from ordr table only and for every row to make another select by ServiceOrderId from info table. This solution should not be used for huge tables.
I have a item table from which i want to get Sum of item quantity
Query:
Select item_id, Sum(qty) from item_tbl group by item_id
Result:
==================
| ID | Quantity |
===================
| 1 | 10 |
| 2 | 20 |
| 3 | 5 |
| 4 | 20 |
The second table is invoice table from which i am getting the item quantity which is sold. I am joining these two tables as
Query:
Select item_tbl.item_id, Sum(item_tbl.qty) as [item_qty],
-isnull(Sum(invoice.qty),0) as [invoice_qty]
from item_tbl
left join invoice on item_tbl.item_id = invoice invoice.item_id group by item_tbl.item_id
Result:
=================================
| ID | item_qty | invoice_qty |
=================================
| 1 | 10 | -5 |
| 2 | 20 | -20 |
| 3 | 10 | -25 | <------ item_qty raised from 5 to 10 ??
| 4 | 20 | -20 |
I don't know if i am joining these tables in right way. Because i want to get everything from item table and available things from invoice table to maintain the inventory. So i use left join. Help please..
Modification
when i added group by item_id, qty i got this:
=================================
| ID | item_qty | invoice_qty |
=================================
| 1 | 10 | -5 |
| 2 | 20 | -20 |
| 3 | 5 | -5 |
| 3 | 5 | -20 |
| 4 | 20 | -20 |
As its a view so ID is repeated. what should i do to avoid this ??
Clearing things up, my answer from the comments explained:
While using left join operation (A left join B) - a record will be created for every matching B record to an A record, also - a record will be created for any A record that has no matching B record, using null values wherever needed to complement the fields from B.
I would advise reading up on Using Joins in SQL when approaching such problems.
Below are 2 possible solutions, using different assumptions.
Solution A
Without any assumptions regarding primary key:
We have to sum up the item quantity column to determine the total quantity, resulting in two sums that need to be performed, I would advise using a sub query for readability and simplicity.
select item_tbl.item_id, Sum(item_tbl.qty) as [item_qty], -isnull(Sum(invoice_grouped.qty),0) as [invoice_qty]
from item_tbl left join
(select invoice.item_id as item_id, Sum(invoice.qty) as qty from invoice group by item_id) invoice_grouped
on (invoice_grouped.item_id = item_tbl.item_id)
group by item_tbl.item_id
Solution B
Assuming item_id is primary key for item_tbl:
Now we know we can rely on the fact that there is only one quantity for each item_id, so we can do without the sub query by selecting any (max) of the item quantities in the join result, resulting in a quicker execution plan.
select item_tbl.item_id, Max(item_tbl.qty) as [item_qty], -isnull(Sum(invoice.qty),0) as [invoice_qty]
from item_tbl left join invoice on (invoice.item_id = item_tbl.item_id)
group by item_tbl.item_id
If your database design is following the common rules, item_tbl.item_id must be unique.
So just change your query:
Select item_tbl.item_id, item_tbl.qty as [item_qty],
-isnull(Sum(invoice.qty),0) as [invoice_qty]
from item_tbl
left join invoice on item_tbl.item_id = invoice invoice.item_id group by item_tbl.item_id, item_tbl.qty
I have two tables, a master table and a general information table. I need to update my master table from the general table. How can I update the master table when the general info table can have slightly different values for the descriptions?
Master
+------+---------+
| Code | Desc |
+------+---------+
| 156 | Milk |
| 122 | Eggs |
| 123 | Diapers |
+------+---------+
Info
+------+---------------+--------+
| Code | Desc | Price |
+------+---------------+--------+
| 156 | Milk | $3.00 |
| 122 | Eggs | $2.00 |
| 123 | Diapers | $15.00 |
| 124 | Shopright Cola| $2.00 |
| 124 | SR Cola | $2.00 |
+------+---------------+--------+
As you can see item 124 has 2 descriptions. It does not matter which description.
My attempt is returning 124 with both codes, I understand my code is looking for both the unique Code and description in the master which is why it returns both 124 but I'm unsure how to fix it.
INSERT INTO MASTER
(
SELECT UNIQUE(Code), Desc FROM INFO A
WHERE NOT EXISTS
(SELECT Code FROM MASTER B
WHERE A.Code = B.Code )
);
I have also tried:
INSERT INTO MASTER
(
SELECT UNIQUE(PROC_CDE), Desc FROM FIR_CLAIM_DETAIL A
WHERE Code NOT IN
(SELECT Code FROM FIR_CODE_PROC_CDE_MSTR B
WHERE A.Code = B.Code )
);
Unique filters the duplicated entries in the SELECTed result set across all columns, not just one key.
When you want to extract the other attributes of a key you filtered, you have to instruct the database to first group the unique keys. To choose one of attributes of a grouped key, we can use an AGGREGATE function. Like MAX(), MIN().
INSERT INTO MASTER
(
SELECT PROC_CDE, MAX(Desc) FROM FIR_CLAIM_DETAIL A
WHERE Code NOT IN
(SELECT Code FROM FIR_CODE_PROC_CDE_MSTR B
WHERE A.Code = B.Code )
GROUP BY PROC_CDE
);
There're analytical functions which can be used for even complex requirements.