I'm struggling, hope you can help me out! The application is an ERP system in MS ACCESS for fashion retailing.
The question: How can I add a row in Table3 with the article's corresponding SizeID1, SizeID2 etc filled according to it's size system of Table2?
Table1: Article details containing size system
ArticleID | SizeType
--------------------
1 | US
2 | EU
Table2: Different size systems for different regions
SizeID | Size | SizeType
------------------------
1 | S | US
2 | M | US
3 | L | US
4 | XL | US
5 | 36 | EU
6 | 38 | EU
7 | 40 | EU
Table3: Order details
OrderID | ArticleID | Size1 | Amount1 | Size2 | Amount2 | Size3 | Amount3
-------------------------------------------------------------------------
1 | 1 | S | 1 | M | 3 | L | 1
2 | 2 | 36 | 2 | 38 | 1 | 40 | 3
3 | 2 | 36 | | 38 | | 40 |
The row with OrderID = 3 is the goal of the insery query for ArticleID 2. I can then enter the amount to the corresponding size. Thanks for your help!!
It's not entirely clear what you're trying to achieve here, but I think that might be because your database design is a bit broken.
You're probably used to working with spreadsheets, becase you seem to have designed your Table3 as if it were a spreadsheet. Any time you end up with repeating fields in a database table (eg. Size1, Size2, Size3....) then it's a sign that you need to normalise more.
Please read up on database normalisation: http://www.studytonight.com/dbms/database-normalization.php (and also google generally for database normalisation for more info).
I suspect you'll need something more like this:
Article table:
ArticleID | ArticleName | SizeType(FK to SizeType table)
1 | Blue T-shirt | 1
2 | Red T-shirt | 2
SizeType table:
SizeTypeID | SizeTypeDescription
1 | US
2 | EU
Sizes table:
SizeID | SizeType(FK) | SizeDescription
1 | 1 | 38
2 | 1 | 40
3 | 2 | M
4 | 2 | L
Items table:
ItemID | ArticleID(FK) | SizeID(FK)
1 | 1 | 1 'Blue T-shirt size 38
2 | 1 | 2 'Blue T-shirt size 40
3 | 2 | 3 'Red T-shirt size M
4 | 2 | 4 'Red T-shirt size L
Orders table:
OrderID | CustomerID (FK) | OrderDate | etc. (other info you need to store about an order)
1 | 2458 | 01/01/2001|
2 | 3452 | 02/02/2002|
Order Details table:
OrderDetailsID | OrderID(FK) | ItemID (FK) | Quantity
1 | 1 | 3 | 6
2 | 1 | 4 | 3
3 | 2 | 1 | 1
So here linking everything back, Customer with ID 2458 has ordered 6x Size M Red T-shirts and 3x Size L Red T-shirts, and Customer with ID 3452 has ordered 1x size 38 Blue T-shirt.
Note You'd also realistically have a PRICE field in either the Items table (if the price varies with the size of an item) or in the Article table (if the price is the same for every size). CustomerID would also link back to a table containing a customer's details (Name, address, username/password etc).
You might also have other things that I've not shown here, for example in either your Articles table or your Items table you'll probably have a supplierID which tells you who you buy that item from, as well as a supplierItemNo which would be a unique code (barcode?) which you use to order that item.
Once your database is structured properly it will be much easier to write queries to insert records etc.
Related
I have data in SQL as follows:
Actual Table
+-------------+--------+------+
| Id | Weight | Type |
+-------------+--------+------+
| 00011223344 | 35 | A |
| 00011223344 | 10 | A |
| 12311223344 | 100 | B |
| 00034343434 | 25 | A |
| 00034343434 | 25 | A |
| 99934343434 | 200 | C |
| 88855667788 | 100 | D |
+-------------+--------+------+
Column ID will always have length of 11 and has data type varchar. I need to create a column Actual Weight and Actual ID from the table above.
Actual Id is dependent on column ID. If the ID starts with 000 than we need to find ID from column ID that does not starts with 000 but characters after that (i.e. 8 characters from right) are similar. Matched ID would be the Actual Id. For example if we look at first 3 ids first 2 starts with 000 and another ID that does not starts with 000 and contains similar 8 characters from right can be found in 3rd row i.e. 12311223344 therefore in derived column Actual ID the first 2 rows would have Actual Id as 12311223344.
Actual Weight is dependent on values in 2 columns ID and Weight. We need to group column Id based on the criteria mentioned above if for any Id that does not starts with 000 but contains another entry that does starts with 000. Then we need to recalculate Weight for Id that does not starts with 000 by adding all Weights of ones starting with 000 and taking difference with one that does not starts with 000.
Example if we look at first 3 rows, in 3rd row we have Id starting with 123 and having entries that have 8 digits from right similar to this one except they start with 000 instead of 123 (i.e. row 1 and 2). For cases starting with 000 Actual Weight would be similar to Weight but for the one starting with 123 Actual Weight would be 100-(35+10)
I am looking for a query that can create these 2 derived column without need of creating any other table/view.
Desired Output
+-------------+-------------+--------+---------------+------+
| Id | Actual ID | Weight | Actual Weight | Type |
+-------------+-------------+--------+---------------+------+
| 00011223344 | 12311223344 | 35 | 35 | A |
| 00011223344 | 12311223344 | 10 | 10 | A |
| 12311223344 | 12311223344 | 100 | 55 | B |
| 00034343434 | 99934343434 | 25 | 25 | A |
| 00034343434 | 99934343434 | 25 | 25 | A |
| 99934343434 | 99934343434 | 200 | 150 | C |
| 88855667788 | 88855667788 | 100 | 100 | D |
+-------------+-------------+--------+---------------+------+
Hmmmm . . . If I'm following this:
select t.*,
(case when id like '000%' then weight
else weight - sum(case when id like '000%' then weight else 0 end) over (partition by actual_id)
end) as actual_weight
from (select t.*,
max(id) over (partition by stuff(id, 1, 3, '')) as actual_id
from t
) t;
Here is a db<>fiddle.
I've got 2 tables, one with an area, actions and quantities, and the other with prices and the goal is to combine the two in a view
table1
areaid integer
bananaunits integer
kilometers_ran integer
dogecoins integer
areaid | bananaunits | kilometers_ran | dogecoin
1 | 0 | 1 | 10
2 | 4 | 2 | 100
table2
rateid integer
description text
cost_per_unit integer
rateid | description | cost_per_unit
1 | price per banana | 0.5
2 | price per kilometers run | 2
3 | price per doge | 1
The intended outcome is to have a view which has the fields as following:
areaid, rateid, description, cost_per_unit, units, combined_cost
areaid| rateid| description| cost_per_unit| units| total_cost
1 | 1 | price per banana | 0.5 | 0 | 0
1 | 2 | per kilometers run | 2 | 1 | 2
1 | 3 | price per doge | 1 | 10 | 10
2 | 1 | price per banana | 0.5 | 4 | 2
2 | 2 | per kilometers run | 2 | 2 | 4
2 | 3 | price per doge | 1 | 100 | 100
In other words, I need to present all the rates per area in individual rows. how to achieve this?
Edit: current query that doesnt work
select areaid, rateid, description, cost_per_unit, units, combined_cost from table1,table2
Since you don't have a joining key and you want a row for each of combination of the area and rates, you're basically looking for a CROSS JOIN also called cartesian product
Might be very simple, but I've been digging fow a few days now... I just can't figure out how to make this SQL query in Access...
In reference to the tables below, i'm looking for the query that can extract all the ITEMS for a specific Shop (ie 1:Alpha) from a specific GROUP (ie 1:Tools), that are NOT in the report for 2014... in this case ITEMS.IDs 6, 8, 9 and 10!
Tables:
Years
ID | Year
-----------------------------------------------
1 | 2014
2 | 2015
Shops
ID | ShopName
-----------------------------------------------
1 | Alpha
2 | Bravo
Items
ID | StockNbr | Description | GroupID
-----------------------------------------------
1 | 00-1200 | Ratchet 1/4 | 1
2 | 00-1201 | Ratchet 1/2 | 1
3 | 00-1300 | Screwdriver Philips No1 | 1
4 | 01-5544 | Banana | 2
5 | 00-4457 | Apple | 2
6 | 21-8887 | Hammer | 1
7 | 21-6585 | Drill | 1
8 | 21-4499 | Multimeter | 1
9 | 21-5687 | Digital Caliper | 1
10 | 22-7319 | File Set | 1
...
Groups
ID | GroupName
-----------------------------------------------
1 | Tools
2 | Fruits
REPORTS
ID | YearID | ShopID | ItemID
-----------------------------------------------
1 | 1 | 1 | 1
2 | 1 | 1 | 2
3 | 1 | 1 | 3
4 | 1 | 1 | 4
5 | 1 | 1 | 7
6 | 1 | 2 | 5
7 | 1 | 2 | 8
8 | 1 | 2 | 10
I've tried this, but then I realize it doesn't take the shops into consideration, it'll list all items that are not listed in reports, so if reports has an item for shop 2, it won't list it either...
SELECT Items.ID, Items.StockNbr, Items.Description, Items.GroupID, Reports.YearID, Reports.ShopID
FROM Reports
RIGHT JOIN Items ON Reports.ItemID = Items.ID
WHERE (((Items.GroupID)=1) AND ((Reports.UnitID) Is Null))
ORDER BY Items.StockNbr;
Thank you!
I think you're looking for an anti-join. There are several ways to do this. Here's one using not in.
select i.* from items i
where i.GroupId = 1
and i.ID NOT IN (
select ItemID from reports r
where r.ShopID = 1
and r.YearID = 2014
)
If the table Reports does not reference Items.ID then there is no available relationship ShopID or YearID
select *
from items
left join reports on items.id = reports.itemid
where reports.itemid IS NULL
I have a table with Bills, each Bill can have 20 subregister.
Example (Top 5 Per Bill, could be up to 60,000 bills)
(TABLE ONE)
Bill | SubRow |
-----+------------+
1000 | 1 |
1000 | 2 |
1000 | 3 |
1000 | 4 |
1000 | 5 |
1001 | 1 |
1001 | 2 |
1001 | 3 |
1001 | 4 |
1001 | 5 |
In another table, I have the Bill number and a Range of subrows
Example:
(TABLE TWO)
Bill | InitialRange | Final Range|
-----+--------------+------------+
1000 | 1 | 2 |
1000 | 4 | 5 |
1001 | 3 | 5 |
In a query I want to achieve the following:
To show , from table One, all records NOT beetween the ranges in table 2.
That means I should get the following set :
Bill | SubRow |
-----+------------+
1000 | 3 |
1001 | 1 |
1001 | 2 |
What I have so far:
Select Bill,SubRow
from TABLE ONE
LEFT join TABLE TWO ON TABLEONE.Bill= TABLETWO.bill
where Subrow < InitialRange and Subrow > FinalRange
but the second condition in the second row in TABLETWO overrides the first for the 1000 bill.
Any idea on how to achieve this?
note(I the tables appears messed up, I will try to fix it)
Image with Example:
http://postimg.org/image/ymc3z2uzx/
Try this:
SELECT * FROM TABLE_ONE WHERE NOT EXISTS
(SELECT * FROM TABLE_TWO
WHERE TABLE_ONE.Bill = TABLE_TWO.Bill
AND TABLE_ONE.SubRow BETWEEN TABLE_TWO.IinitialRange AND TABLE_TWO.FinalRange)
I have a two tables
cars: contains hierarchy data about cars
+-----+-------------+-----------+
| id | description | parent_id |
+-----+-------------+-----------+
| 1 | All cars | 1 |
| 30 | Toyota | 1 |
| 34 | Yaris | 30 |
| 65 | Yaris | 30 |
| 87 | Avensis | 30 |
| 45 | Avensis | 30 |
| 143 | Skoda | 1 |
| 199 | Octavia | 143 |
| 12 | Yeti | 143 |
+-----+-------------+-----------+
car_mapping: contains mapping data where duplicate cars (with different ids) are mapped to one id.
+--------+----------+--------+
| car_id | car_name | map_id |
+--------+----------+--------+
| 34 | Yaris | 1 |
| 65 | Yaris | 1 |
| 87 | Avensis | 2 |
| 45 | Avensis | 2 |
| 199 | Octavia | 3 |
| 12 | Yeti | 4 |
| 30 | Toyota | 5 |
| 143 | Skoda | 6 |
| 1 | All cars | 0 |
+--------+----------+--------+
Now, the idea is to create a third table, cars_new, based on cars and car_mapping which removes duplicates and re-keys the hierarchy in the cars table based on the map_id field in the car_mapping table. Here is the resulting cars_new:
+--------+----------+---------------+
| map_id | car_name | parent_map_id |
+--------+----------+---------------+
| 0 | All | 0 |
| 1 | Yaris | 5 |
| 2 | Avensis | 5 |
| 3 | Octavia | 6 |
| 4 | Yeti | 6 |
| 5 | Toyota | 0 |
| 6 | Skoda | 0 |
+--------+----------+---------------+
Here is the SQL Fiddle for this question. Any ideas how to re-key this hiearchy?
select distinct cm.map_id, cm.car_name, cm2.map_id parent_map_id
from cars c, car_mapping cm, car_mapping cm2
where c.id = cm.car_id
and c.parent_id = cm2.car_id(+)
order by cm.map_id;
PS: in your car_mapping table, you need one extra line (first one below) to get exactly the result you want:
+--------+----------+--------+
| car_id | car_name | map_id |
+--------+----------+--------+
| 1 | All | 0 |
| 34 | Yaris | 1 |
| 65 | Yaris | 1 |
Etc..
Based on #Majid LAISSI's accepted answer, this seems to work both in Oracle and SQL Server:
select distinct cm.map_id, cm.car_name, cm2.map_id as parent_map_id
from cars c
left outer join car_mapping cm on c.id = cm.car_id
left outer join car_mapping cm2 on c.parent_id = cm2.car_id
order by cm.map_id;
You don't have a hierarchy, and you're better off not creating one. Observe that your "cars" table doesn't describe cars; it merely assigns a string to a number (and another number to that number). Right from the get-go, "all cars" isn't a car, and "Toyota" is a car manufacturer, not a car.
The solution -- which would help with your uniqueness issue and simplify your queries -- is to use one table for each distinct thing:
manufactures { mfg_id, name } -- e.g. GM, Ford
makes { make_id, name, mfg_id } -- e.g. Chevrolet, Lincoln; links to manufactures
models { name, make_id } -- e.g. Yaris, etc.; links to makes.
Be sure to make "name" unique in each of the tables to prevent spurious IDs from being created.
This will let you assign new attributes to these things as they arise, such as the years they were made or how many were sold, or how many doors each model comes in. It will also let you prevent "relations" of Ford to GM or, say, making Yaris the parent of "all cars".
(BTW, I suggest you eschew "map" or "mapping" in a table name, because it doesn't say anything. Every table relates the elements in the row to each other. Every table maps the key to its values. The good news is that your car_mapping table disappears in the new design.)
As for how to convert the existing cars table, it will be a nuisance. Assuming cars_mapping is right, you'll be able to insert into each table, joining to it and taking the min(id) while grouping by name. You'll need three such queries, followed by some careful eyeballing to check for, er, misalignment.