How can I link my Junction table to my main table - sql

I have a SQL database with the main table called Results. This table stores a record of results of tests that are run nightly.
The Results table has many fields but for arguments say lets just say for now it looks like this:
ResultID (Unique key field generated upon insert)
Result (nvchar10)
What I wanted to be able to record was a list of tags used in the tests that were run. The tags may be different for each result and an array of them are stored.
I created a junction table as shown below called Tags:
TagID (int key field unique generated at runtime)
ResultID (int)
ScenarioTag (nvchar128)
FeatureTag (nvchar128)
So what im looking to do is to link these 2 together. I'm not so great with databases ill be honest.
I was thinking that when I save the test results with my normal SQL query immediately after I would loop through each tag and save the tags to this new table but maybe i'm wrong here?
Psuedocode:
//Returned from previous SQL statement that inserted results values into the DB
int ResultID = SQLQueryReturnValue;
Foreach TAG in TAGS
{
string SQLQuery = "INSERT INTO TAGS (ResultID, ScenarioTag, FeatureTag)(#ResultID, #ScenarioTag, #FeatureTag)";
CmdSql.Parameters.AddWithValue("#ResultID", ResultID);
CmdSql.Parameters.AddWithValue("#ScenarioTag", TAG.Scenario);
CmdSql.Parameters.AddWithValue("#FeatureTag", TAG.Feature);
CmdSql.CommandText = SQLQuery;
CmdSql.Execute();
}
Heres an example of what each table might actually look like:
Results Table
|ResultID | Result |
| 10032 | Pass |
| 10031 | Fail |
| 10030 | Fail |
Tags Table
| TagID | ResultID | ScenarioTag | FeatureTag |
| 6 | 10032 | Cheque | Trading |
| 5 | 10032 | GBP | Sales |
| 4 | 10031 | Direct Credit | Trading |
| 3 | 10031 | GBP | Purchase |
| 2 | 10030 | Wire | Dividends |
| 1 | 10030 | USD | Payments |
So finally onto my question...Is there a way that I can physically link this new "Tags" table to my results table. Its informally linked in a way using the ResultID but theres no physical link.

Is it this you're looking for? (Assumption: This query is looking from results. They do not necessarily have to have Tags...)
SELECT *
FROM Results
LEFT JOIN Tags ON Results.ResultID=Tags.ResultID
EDIT: Maybe I did not understand, what you mean by "physically". You could add a foreign key constraint:
ALTER TABLE Tags ADD CONSTRAINT FK_Tags_Results FOREIGN KEY (ResultID) REFERENCES Results(ResultID);
This constraint adds a relation to these tables, making sure, that only values existing in Results are allowed in Tags as "ResultID". On the other hand you cannot delete a Result row with existing children in Tags...
If you do this you could alter the top query to:
SELECT *
FROM Tags
INNER JOIN Results ON Results.ResultID=Tags.ResultID
Now you are looking from Tags (leading table) and you know, that each tag must have a ResultID (INNER JOIN).

Related

Auto generate columns in Microsoft Access table

How can we auto generate column/fields in microsoft access table ?
Scenario......
I have a table with personal details of my employee (EmployDetails)
I wants to put their everyday attendance in an another table.
Rather using separate records for everyday, I want to use a single record for an employ..
Eg : I wants to create a table with fields like below
EmployID, 01Jan2020, 02Jan2020, 03Jan2020,.........25May2020 and so on.......
It means everyday I have to generate a column automatically...
Can anybody help me ?
Generally you would define columns manually (whether that is through a UI or SQL).
With the information given I think the proper solution is to have two tables.
You have your "EmployDetails" which you would put their general info (name, contact information etc), and the key which would be the employee ID (unique, can be autogenerated or manual, just needs to be unique)
You would have a second table with a foreign key to the empployee ID in "EmployDetails" with a column called Date, and another called details (or whatever you are trying to capture in your date column idea).
Then you simply add rows for each day. Then you do a join query between the tables to look up all the "days" for an employee. This is called normalisation and how relational databases (such as Access) are designed to be used.
Employee Table:
EmpID | NAME | CONTACT
----------------------
1 | Jim | 222-2222
2 | Jan | 555-5555
Detail table:
DetailID | EmpID (foreign key) | Date | Hours_worked | Notes
-------------------------------------------------------------
10231 | 1 | 01Jan2020| 5 | Lazy Jim took off early
10233 | 2 | 02Jan2020| 8 | Jan is a hard worker
10240 | 1 | 02Jan2020| 7.5 | Finally he stays a full day
To find what Jim worked you do a join:
SELECT Employee.EmpID, Employee.Name, Details.Date, Details.Hours_worked, Details.Notes
FROM Employee
JOIN Details ON Employee.EmpID=Details.EmpID;
Of course this will give you a normalised result (which is generally what's wanted so you can iterate over it):
EmpID | NAME | Date | Hours_worked | Notes
-----------------------------------------------
1 | Jim | 01Jan2020 | 5 | ......
1 | Jim | 02Jan2020 | 7 | .......
If you want the results denormalised you'll have to look into pivot tables.
See more on creating foreign keys

MS ACCESS - cannot subtract returned values from a query from values in another table

I have two tables: Project and Invoice
Project Table:
ID | UR_No | Budget_Total | Budget_To_Date
1 | 329000 | 150000.00 |
2 | 403952-C | 33000 |
Invoice Table:
ID | URID | InvAmount
1 | 329000 | 157.00
2 | 329000 | 32.00
3 | 403952-C| 193.00
Invoice table has amounts charged to a project. A project has a unique UR number (UR_No) and invoices have duplicate UR numbers (URID), meaning the same project gets billed monthly and has different invoice numbers.
What I would like to achieve is:
ID | UR_No | Budget_Total | Budget_To_Date
1 | 329000 | 150000.00 | 149811.00
2 | 403952-C | 33000 | 32807
First, an aggregate query is done on the Invoice table to get the running total of money charged to the project:
SELECT Invoice.URID, Sum(Invoice.InvAmount) AS total
FROM Invoice
GROUP BY Invoice.URID;
This returns the following:
URID | InvAmount
329000 | 189.00
403952-C| 193.00
This is then exported to a table in the DB named Invoice_Totals
I then want to join the Invoice_Totals table to the Project table using UR_No & URID and calculate an empty existing field "Budget_to_Date" in the Project table by subtracting Invoice_Totals.total in the query table from a field named Budget_total in the project table. Before attempting that, I would just like the query to return the values:
SELECT Project.Budget_Total - Invoice_Totals.total
FROM Project INNER JOIN Invoice_Totals ON Project.UR_No = Invoice_Totals.URID;
This returns the error:
Cannot join on Memo, OLE, or hyperlink object (Project.UR_No=Invoice_Totals.URID)
I looked up an SO post and tried using left 255:
SELECT Project.Budget_Total - Invoice_Totals.total
FROM Project INNER JOIN Invoice_Totals ON left(Project.UR_No,255) = left(Invoice_Totals.URID, 255);
This returns nothing. If possible, How can I subtract the aggregate field from budget total in the Project table in either the Budget_To_Date field or in a new field?
Your comment states linking fields are LongText which is synonymous with Memo data type, therefore the error message clearly identifies cause. Change the field type to ShortText.
However, really should use ID field in Project table as primary key and save that instead of UR_No into Invoice table. Numbers are more efficient keys.

Getting difference from two tables and deleting it in SQL Server

I am facing issue in writing the logic of a query that deletes data which are not existing in either of the 2 tables.
For example, I have a tables "Stage" and "Parent". I am using composite primary keys to uniquely identity records(multiple primary keys).
Stage structure and Data
S_Column1(Primary) | PRIDATA1 | PRIDATA4
S_Column2(Primary) | PRIDATA2 | PRIDATA5
S_Column3(Primary) | PRIDATA3 | PRIDATA6
S_Column4 | DJUC | JDNC
S_Column5 | DSSDC | JDDOS
Parent structure and Data
P_Column1(Primary) | PRIDATA1 | PRIDATA4 | PRIDATA7
P_Column2(Primary) | PRIDATA2 | PRIDATA5 | PRIDATA8
P_Column3(Primary) | PRIDATA3 | PRIDATA6 | PRIDATA9
P_Column4 | DJUC | JDNC | FFED
P_Column5 | DSSDC | JDDOS | NHUY
The above is just a sample of structure and data of two tables.
So basically what I want to do is write a query to delete the row that have
PRIDATA7 PRIDATA8 and PRIDATA9 as primary key because their entries are not present in STAGE TABLE.
I am not skilled, but I know I need to find out matching data using JOIN and delete the rest of the data from PARENT TABLE whose entries aren't present in STAGE TABLE
PS: I will be using this in a Trigger.
Try not exists
delete from parent
where not exists (
select 1
from stage s
where s.S_Column1 = parent.S_Column1 and s.S_Column2 = parent.S_Column2 and s.S_Column3 = parent.S_Column3)
You might be looking for the EXCEPT operator.
Read here: https://msdn.microsoft.com/pl-pl/library/ms188055(v=sql.110).aspx

Gather single rows from multiple tables in Microsoft Access

I have several tables in Microsoft Access 2013, all of which follow the same format of:
ID | Object | Person 1 | Person 2 | Person 3 |
ID | String | Yes/No | Yes/No | Yes/No |
What I would like to do is make a query where I put in a string value for each table and it prints out the entire row, with each string getting its own row, so it looks like:
ID Number | Object | Person 1...
Table 1 ID | Table 1 String | Table 1 Yes/No...
Table 2 ID | Table 2 String | Table 2 Yes/No...
Every time I try, though, it puts all the data into one extremely long row that's impossible to look at. All of my searching has only turned up people trying to do the exact opposite of what I'm doing, though, so I must be missing something obvious. Any tips?

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