Chaining records by fields - sql

I have a data set (currently in Access 2007 format) which has 2 tables, simplified to
category
categoryid | category name | first item
1 | category 1 | i1
2 | category 2 | i2
3 | category 3 | i3
items
itemid | item name | next item
i1 | item 1 | i4
i2 | item 2 | i5
i3 | item 3 | i6
The category defines the first item and each subsequent item references the next item until an item's next item is NULL, so it should be possible to find all the items for a particular category by continually following the next item field. Is this possible in SQL or do I need to drop out to a script to process it? I was hoping that there was at least a half-way house in that a SQL query could get me some of the way before using VBScript or similar.
I could import this to SQL server if that provides additional functionality not available in Access.

On SQL Server you can write such query using Common Table Expressions. See here: http://msdn.microsoft.com/en-us/library/ms186243.aspx
Not sure if it's possible in Access, though.

Related

Database Design: Inventory with multilevel packaging

I'm trying to develop a database for my inventory. But I have no idea how to keep track of multilevel packaging.
For example:
I currently have a products and positions table
products
Id | Name
================
1013 | Metal
1014 | Wood
positions
id | Name
================
1 | 1-1-1-1
2 | 1-1-1-2
And my inventory table I was thinking of doing something like this:
Let's say I stored 1 box with 1000 Metal and 1 box with 500 Wood at position 1-1-1-1
ItemId | ProductId | Quantity | PositionId
==========================================
1 | 1013 | 1000 | 1
2 | 1014 | 500 | 1
So I'll label those two boxes with a barcode 1 and 2 respectively, so if I scan them, I can check this table to see the product and quantity inside them.
But I can also put these 2 boxes (1 and 2) inside another box (let's call it box 3), which would generate a new barcode for it that, if scanned, will show both previous boxes and its items. And store this box 3 in another position
And I can also put this box 3 inside a pallet, generating a new code and so on. So basically I can multilevel package N times.
What is the best table structure to keep track of all of this? Thanks in advance for any help!
I would add another column to the products table, make it a BIT and maybe call it BOM, BillOfMaterials, or whatever makes sense to you
So your products Table would look like this
Then you could create another table called BillOfMaterials
Quantity is how many of your products are needed to make up your new product. So for this example 2 metal and 1 wood make a pencil.
I was able to make a good structure:
My products and positions are the same but I created a stock table like:
id | product_id | amount | parent_id | position_id
=====================================================
1 | 1013 | 1000 | 4 | 1
2 | 1013 | 1000 | 4 | 1
3 | 1014 | 500 | 4 | 1
4 | 1234 | NULL | NULL | 1
The 1234 (random id) is a box that contains 2000 metal and 500 wood. I dont save this box in the product table.
When I scan the box with id 3, I perform a recursive cte query:
with recursive bom as (
select *, 1 as level
from testing.stock
where id = '4' #scanned id
union all
select c.*, p.level + 1
from testing.stock c
join bom p on c.parent_id = p.id
)
select product_id as product, sum(amount), position_id
from bom b
left join testing.product pd on b.product_id = pd.id
where pd.id is not null
group by product_id, position_id
which returns:
sum | product | position
2000 | 1013 | 3
500 | 1014 | 3
to get by position I just run a variation of the above query. To perform an update I get the Ids inside that box and run a
update testing.stock set position = '2' where id in (#variation of above query)
I hope this helps someone. This works for N packaging level

Trying to find non-duplicate entries in mostly identical tables(access)

I have 2 different databases. They track different things about inventory. in essence they share 3 common fields. Location, item number and quantity. I've extracted these into 2 tables, with only those fields. Every time I find an answer, it doesn't get all the test cases, just some of the fields.
Items can be in multiple locations, and as a turn each location can have multiple items. The primary key would be location and item number.
I need to flag when an entry doesn't match all three fields.
I've only been able to find queries that match an ID or so, or who's queries are beyond my comprehension. in the below, I'd need a query that would show that rows 1,2, and 5 had issues. I'd run it on each table and have to verify it with a physical inventory.
Please refrain from commenting on it being silly having information in 2 different databases, All I get in response it to deal with it =P
Table A
Location ItemNum | QTY
-------------------------
1a1a | as1001 | 5
1a1b | as1003 | 10
1a1b | as1004 | 2
1a1c | as1005 | 15
1a1d | as1005 | 15
Table B
Location ItemNum | QTY
-------------------------
1a1a | as1001 | 10
1a1d | as1003 | 10
1a1b | as1004 | 2
1a1c | as1005 | 15
1a1e | as1005 | 15
This article seemed to do what I wanted but I couldn't get it to work.
To find entries in Table A that don't have an exactly matching entry in Table B:
select A.*
from A
left join B on A.location = B.location and A.ItemNum = B.ItemNum and A.qty = B.qty
where B.location Is Null
Just swap all the A's and B's to get the list of entries in B with no matching entry in A.

MS access 2007 - checklist options(multiple) to be stored in a column of the database

I have a situation like - the customer form in MS access 2007 have list of documents provided by customers. The list is in the checklist format. Assuming there are 6 documents under the checklist. So if the one or more checklists are selected, all the selected list should be saved in the database column named "Documents_Provided". So in order to achieve this scenario what should I have to do. How should my database field "Documents_provided" should be declared and what do I have to write in VBA code.
As per your Question heading suggests "Multiple to be stored in a Column of the database" is a very bad table design, it breaks one of the rules of Fundamentals of Database Design, Data should be atomic.
The system you should be having is a One to Many, between the Customer and Document table. The Customer table will normally have the basic customer information; one side of the relationship, and the Documents table will have all the documents that pertain to each Customer; many side of the relationship. In Addition you will have another table Document Category that will say what are all the documents that needs/can have for each customer. So sample data in your table will be something like,
tbl_Customers
`````````````
ID | customerName | customerArea
----+-------------------+------------------
1 | Paul | Bournemouth
2 | Eugin | Bristol
3 | Francis | London
tbl_DocumentsCategory
`````````````````````
ID | DocumentName
----+---------------------------
1 | Address Proof
2 | Photo ID
3 | Employer Certificate
tbl_CustomersDocument
`````````````````````
ID | CustomerID | DocumentID
----+---------------+--------------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 1
5 | 2 | 3
6 | 3 | 2
So when you need to get the list of Documents each Customer has, you simply JOIN the two tables to get the right information. This is the standard and efficient way to organize the data. I hope this helps, and you stick to this.

Best way to include a dynamic number of related table rows as columns in an SQL result set

I have three tables with data like this:
An item table that contains basic info per item. Each item has one 'template' that determines a set of meta data for items with that template.
id | name | template_id
--------------------------
1 | Thing1 | t1
2 | Thing2 | t2
A template_fields table that contains a row for each type of meta data that could be associated with an item with particular template. It looks something like the table below. Here there are two templates, one with two fields and one with a single field. (The number of fields can vary per template.)
id | key | order
--------------------
t1 | color | 1
t1 | size | 2
t2 | year | 1
Finally, there is a meta_data table that contains the actual values associated with the template fields for each item:
item_id | template_id | key | value
--------------------------------------
1 | t1 | color | Red
1 | t1 | size | 2
2 | t2 | year | 2014
Now, in my application I want to have a per-template view of this data so that if I want to see items of template a particular template each row in the result set contains a column for each field in the corresponding template. For example, items in template t1 would look like this:
item_id | name | color | size
--------------------------------
1 | Thing1 | Red | 2
Similarly for items in template t2
item_id | name | year
------------------------
1 | Thing2 | 2014
Is there a way to do this in a single SQL query? (Keep in mind that I do not know the number of fields in a template until runtime. I am also not concerned with having a view that contains fields from items with different templates; one template at a time.)
My best whack at a solution so far is something like the pseudo code below, but please let me know if you think there is a better way (including a better table structure) to accomplish what I want.
fields = SELECT template_fields.key, meta_data.value FROM template_fields
JOIN meta_data ON
meta_data.template_id = template_fields.id
AND meta_data.key = template_fields.key
WHERE meta_data.item_id IN (SELECT id FROM item WHERE template='t1')
ORDER BY meta_data.item_id, template_fields.order
items = SELECT * FROM item WHERE template='t1'
i = 0
for item in items:
while fields[i].item_id = item.id:
item[fields[i].key] = fields[i].value
i += 1
Here's an SQL Fiddle link to play with

MySQL query for initial filling of order column

Sorry for vague question title.
I've got a table containing huge list of, say, products, belonging to different categories. There's a foreign key column indicating which category that particular product belongs to. I.e. in "bananas" row category might be 3 which indicates "fruits".
Now I added additional column "order" which is for display order within that particular category. I need to do initial ordering. Since the list is big, I dont wanna change every row by hand. Is it possible to do with one or two queries? I dont care what initial order is as long as it starts with 1 and goes up.
I cant do something like SET order = id because id counts from 1 up regardless of product category and order must start anew from 1 up for every different category.
Example of what I need to achieve:
ID | product | category | Order
1 | bananas | fruits | 1
2 | chair | furniture | 1
3 | apples | fruits | 2
4 | cola | drinks | 1
5 | mango | fruits | 3
6 | pepsi | drinks | 2
(category is actually a number because it's foreign key, in example I put names just for clarification)
As you see, order numbers start anew from 1 for each different category.
Sounds like something a SQL procedure would be handy for.
Why not just set the order to the category? That is, why not:
update Table
set SortOrder = Category;
As an aside, you cannot have a column named order -- that is a reserved word in SQL.