UPDATE statement won't update anything - sql

I've been creating a recipe database for a class project using SSMS. I have one table with all the recipe names that I'd inserted into a lookup table (RecipeDetails), but I'd left out their associated IDs, so I wanted to write a bit of code to update my table with those values. I feel like this code should work fine (it seemed to work in the past, but I screwed up something unrelated and had to restore my most recent database backup), but now it just isn't. It says it's affected all the rows I expect it to affect, but those rows still list the RecipeID as NULL.
I'm pulling my data from RecipesTable, which includes the names of each recipe and an ID for each. In RecipeDetails I have a column for RecipeName, RecipeID, Ingredient, IngredientID, and an ID for each row in the table. As of now, I have all my recipes in the table, but not their associated ID. I would like to move the ID's over from one table to another.
UPDATE rd
SET rd.RecipeID = rt.RecipeID
FROM RecipeDetail AS rd
FULL JOIN RecipesTable AS rt ON rd.RecipeID = rt.RecipeID
WHERE rt.RecipeName = rd.RecipeName;

You should use an inner join rather than an outer join.
UPDATE rd
SET rd.RecipeID = rt.RecipeID
FROM RecipeDetail rd JOIN
RecipesTable rt
ON rd.RecipeName = rt.RecipeName;

Related

SQL Query across two tables only show most recently updated result per tag address

I have two tables: violator_state and violator_tags
violator_state:
m_state_id
is_violating
m_translatedid
m_tag
m_violator_tag
This table holds the "tags" which has an unchanging row count of 10 in this case. The purpose is to list out each tag present, connect the full tag address (m_violator_tag) with its shorthand name (m_tag) and state whether it is in "violation". I need to use this table as reference because of the link between m_violator_tag and m_tag.
violator_tags
m_violator_id
m_eval_time_from
m_eval_time_to
m_tag
m_tag_peers
m_tag_position
This table is constantly having new rows added to it holding the information of what tags are in violation with a specific tag. So it would show T6 in violation with T1,T2,T9 ect.
I am looking to create a query which joins the two tables to show only the most recently updated (largest m_eval_time_from) for each tag.
I am using the following query to join the two tables but I expect m_translatedid and m_tag to match but they do not. Unsure why.
SELECT violator_state.m_violator_tag, violator_state.is_violating, violator_state.m_translatedid, violator_tags.m_tag, violator_tags.m_eval_time_to, violator_tags.m_tag_peers,
violator_tags.m_tag_position, violator_tags.m_eval_time_from
FROM violator_tags CROSS JOIN
violator_state
Violation_state table
violation_tags table
results of my (incorrect) query
Any suggestions on what I should try?
Your CROSS JOIN will give you a cartesian product where EVERY row in the first table is paired with ALL the rows in the second table e.g. if you have 10 rows in each, you will get 10 x 10 = 100 rows in the result! I believe you need to join the tables on the m_tag column and select the violator_tags row with the latest date. The query below should do this for you (though you haven't provided your question in a manner that makes it easy for me to double-check my code - see the link provided by a_horse_with_no_name for more on this or use a website like db-fiddle to set up your example).
SELECT vs.m_violator_tag,
vs.is_violating,
vs.m_translatedid,
vt.m_tag,
vt.m_eval_time_to,
vt.m_tag_peers,
vt.m_tag_position,
vt.m_eval_time_from
FROM violator_tags vt
JOIN violator_state vs
ON vt.m_tag = vs.m_tag
AND vt.m_eval_time_from = (SELECT MAX(vt.m_eval_time_from)
FROM violator_tags
WHERE m_tag = vt.m_tag)

Using coalesce with left joins to populate master table with most recent data

I have 3 tables, 1 master and 2 tables containing the most recent data that should be populated (update) into the master table.
For this I need to create a transform view, that left joins the two tables with the master. For each value I should use the COALESCE function to always pick the value from one of the two tables with the most recent data, before the value in the master table.
Some fields only exist in the master table and some needs to be updated with the new data from the two other tables.
So far I've been using the COALESCE function like so:
COALESCE(System.tMirror_Roadpiece.Roadcode, System.tMirror_MasterTable.Roadcode)
This should select the value from the tMirror_Roadpiece table if it is not null.
My problem is that I am unsure how to correctly join the tables, while making sure my COALESCE functions work as intended.
Currently my joins look like this:
FROM [System].[tMirror_Roadpiece]
left join System.tMirror_MasterTable on System.tMirror_Roadpiece.Id = System.tMirror_MasterTable.Id
left join System.tMirror_Zipcodes on System.tMirror_MasterTable.Zipcode = System.tMirror_Zipcodes.Zipcode
But when I execute my SELECT statement I get no data back. How should I best structure my joins to update my master table with the data in the other two tables? One table is joined on the Id, while the other is joined on Zipcode.
My intended output is a master table with relevant data updated from the two other tables, while leaving the rest of the data in the master untouched.
Let me know if you need more information.
Edit: Sample data
Master table data (CSV):
123,1,2015-05-07T13:00:48.623,2015-05-07T13:00:48.623,3446,Hospitalsringen,Hospitalsringen,68,,,,5260,Odense S,,,0461,Odense,350455,"Hollufgård Hgd., Fraugde",1f,704050,590541.26,6135939.39,55.36141744,10.42832236,A,5,TN,200,100m_61359_5905,1km_6135_590,10km_613_59,2015-05-07T13:00:49.533,00000667-2566-47c9-9ba0-f5ec6b8ce50f,1,2015-05-07T13:00:48.533,2018-07-04T18:00:00.000,1083,Region Syddanmark,"Hollufgård Hgd., Fraugde",04613436__68_______,9148,Tornbjerg,1465,Fyns Politi,1135,Retten i Odense,0043,Odense Syd,Byzone,350455,1f,704050,04613436__68,22.1,d90e9338-0470-41bc-8ecb-6f71dd912ff0,11604d86-af45-11e7-847e-066cff24d637,Ekstern,B,V0,10.42845878,55.36232181,25,Rosengårdskolen,1,,02da5b79-929c-f1b5-e053-d280220ac400
Edit: SQL code
SELECT System.tMirror_MasterTable.[Infohub_RowId]
,System.tMirror_MasterTable.[Infohub_CreatedDate]
,System.tMirror_MasterTable.[Infohub_ValidityDate] AS [Infohub_ModifiedDate]
,System.tMirror_MasterTable.Infohub_HasChanged
,COALESCE(System.tMirror_Roadpiece.Id, System.tMirror_MasterTable.Id)
,[Status]
,System.tMirror_MasterTable.[Oprettet]
,System.tMirror_MasterTable.[Aendret]
,COALESCE(System.tMirror_Roadpiece.Vejkode, System.tMirror_MasterTable.Vejkode)
,COALESCE(System.tMirror_Roadpiece.Vejnavn, System.tMirror_MasterTable.Vejkode)
,COALESCE(System.tMirror_Zipcodes.Zipcode, System.tMirror_MasterTable.Zipcode)
,COALESCE(System.tMirror_Zipcodes.Zipcodenavn, System.tMirror_MasterTable.Zipcodenavn)
,COALESCE(System.tMirror_Roadpiece.Kommunekode, System.tMirror_MasterTable.Kommunekode)
,System.tMirror_MasterTable.[Kommunenavn]
,System.tMirror_MasterTable.[Regionskode]
,System.tMirror_MasterTable.[Regionsnavn]
,COALESCE(System.tMirror_Roadpiece.Navngivenvej_id, System.tMirror_MasterTable.Navngivenvej_id)
FROM
[System].[tMirror_Roadpiece] left join System.tMirror_MasterTable on System.tMirror_Roadpiece.Id = System.tMirror_MasterTable.Id
left join System.tMirror_Zipcodes on System.tMirror_MasterTable.Zipcode = System.tMirror_Zipcodes.Zipcode
WHERE
System.tMirror_MasterTable.Infohub_HasChanged = 1

Multiple JOIN statements returning multiple rows

I believe I need a fresh set of eyes, my attention has been pulled elsewhere at work and I have not had the time to figure this out. So I'm hoping someone may be kind enough to offer a suggestion.
Here is an abbreviated version of my SQL statement:
SELECT
PR.PROJECTNUM,
PR.PROJECTNUMBER,
PR.AMRNUM,
W.WONUM,
C.PONUM,
C.POLINENUM
FROM PROJECT PR
INNER JOIN WORKORDER W
ON PR.PROJECTNUM = W.PROJECTNUM
OR PR.PROJECTNUMBER = W.PROJECTNUMBER
OR PR.AMRNUM = W.AMRNUM
INNER JOIN
(SELECT PL.WONUM, P.PONUM, PL.POLINENUM FROM PO P
INNER JOIN POLINE PL ON P.PONUM = PL.PONUM) C
ON W.WONUM = C.WONUM;
As you can see, I'm joining 4 tables here.PO to POLINE to WORKORDER to PROJECT. The issue lies with the multiple joining attributes between the WORKORDER and PROJECT table.
I do not know beforehand which attribute/field will be populated with a value in the WORKORDER table, but at least one will be...but sometimes all three. The duplication occurs when more than one of the joining attributes in the WORKORDER table is populated with a matching value in the PROJECT table.
It's almost as if I need to test for the presence of a value in the joining attribute from the WORKORDER table before I execute the above SQL....and if more than one is populated with a value, then I need to find which one of the PROJECTattributes has a matching value....geez...even typing it out is making my head spin...lol
I may need to come back in the morning and add a little more context, my brain is fried at the moment :)
Thanks for reading!

What is the correct SQL statement to get the Row Source for a table, based on another field?

I currently have a schema set up in the following manner:
The table tblCategoryRiskArea is set up as an intermediate table for the many-to-many relationship that can exist between Categories and RiskAreas.
Within the tblBase table, I would like to make it so that the RiskArea choices are dependant upon the Category choice. MS Access allows you to set a Lookup for a field in a table based upon a Row Source SQL statement. I am having trouble figuring out the correct SQL statement to define the Row Source for RiskArea dependant upon Category. This:
SELECT tblRiskAreas.RiskAreaID, tblRiskAreas.RiskArea
FROM tblRiskAreas INNER JOIN
((tblCategories INNER JOIN tblBase
ON tblCategories.CategoryId = tblBase.Category)
INNER JOIN tblCategoryRiskArea
ON tblCategories.CategoryId = tblCategoryRiskArea.Category)
ON (tblRiskAreas.RiskAreaID = tblCategoryRiskArea.RiskArea)
AND (tblRiskAreas.RiskAreaID = tblBase.RiskArea)
WHERE (((tblCategoryRiskArea.Category)=[tblBase]![Category]))
ORDER BY tblRiskAreas.RiskAreaID;
is the best I've come up with so far, using MS Access' Query Builder, so all of the Inner Joins have been created just by my having defined the relationships between the tables and dragging them into the Query Builder. This query returns nothing, however.
I suspect that it may have something to do with the circular nature of the relationships I set up?
Thank you.
Edited: tblRiskArea contains 4 RiskAreas, as follows:
Environmental
Health
Safety
Security
Each Category can fall into one or two of these RiskAreas, so the tblCategoryRiskArea creates the relationship bewtween them.
First remove Category and RiskArea from tblBase and replace them for CategoriRiskAreaID
You will show in your form 2 combos. First combo Catagory data source:
Select CategoryId,Category from tblCategories
Second combo Risk Areas data source:
Select a.CategoryRiskId, b.RiskArea
from tblCategoryRiskArea a
inner join tblRiskArea b
where a.RiskAreaId=b.RiskAreaId
AND a.category = #ComboBoxCategorySelectedItem
Now you have the value to insert in tblBase, ComboBoxSelectedItem is tblCategoryRiskArea.CategoryRiskId

Update values in each row based on foreign_key value

Downloads table:
id (primary key)
user_id
item_id
created_at
updated_at
The user_id and item_id in this case are both incorrect, however, they're properly stored in the users and items table, respectively (import_id for in each table). Here's what I'm trying to script:
downloads.each do |download|
user = User.find_by_import_id(download.user_id)
item = item.find_by_import_id(download.item_id)
if user && item
download.update_attributes(:user_id => user.id, :item.id => item.id)
end
end
So,
look up the user and item based on
their respective "import_id"'s. Then
update those values in the download record
This takes forever with a ton of rows. Anyway to do this in SQL?
If I understand you correctly, you simply need to add two sub-querys in your SELECT statement to lookup the correct IDs. For example:
SELECT id,
(SELECT correct_id FROM User WHERE import_id=user_id) AS UserID,
(SELECT correct_id FROM Item WHERE import_id=item_id) AS ItemID,
created_at,
updated_at
FROM Downloads
This will translate your incorrect user_ids to whatever ID you want to come from the User table and it will do the same for your item_ids. The information coming from SQL will now be correct.
If, however, you want to update the tables with the correct information, you could write this like so:
UPDATE Downloads
SET user_id = User.user_id,
item_id = Item.item_id
FROM Downloads
INNER JOIN User ON Downloads.user_id = User.import_id
INNER JOIN Item ON Downloads.item_id = Item.import_id
WHERE ...
Make sure to put something in the WHERE clause so you don't update every record in the Downloads table (unless that is the plan). I rewrote the above statement to be a bit more optimized since the original version had two SELECT statements per row, which is a bit intense.
Edit:
Since this is PostgreSQL, you can't have the table name in both the UPDATE and the FROM section. Instead, the tables in the FROM section are joined to the table being updated. Here is a quote about this from the PostgreSQL website:
When a FROM clause is present, what essentially happens is that the target table is joined to the tables mentioned in the fromlist, and each output row of the join represents an update operation for the target table. When using FROM you should ensure that the join produces at most one output row for each row to be modified. In other words, a target row shouldn't join to more than one row from the other table(s). If it does, then only one of the join rows will be used to update the target row, but which one will be used is not readily predictable.
http://www.postgresql.org/docs/8.1/static/sql-update.html
With this in mind, here is an example that I think should work (can't test it, sorry):
UPDATE Downloads
SET user_id = User.user_id,
item_id = Item.item_id
FROM User, Item
WHERE Downloads.user_id = User.import_id AND
Downloads.item_id = Item.import_id
That is the basic idea. Don't forget you will still need to add extra criteria to the WHERE section to limit the rows that are updated.
i'm totally guessing from your question, but you have some kind of lookup table that will match an import user_id with the real user_id, and similarly from items. i.e. the assumption is your line of code:
User.find_by_import_id(download.user_id)
hits the database to do the lookup. the import_users / import_items tables are just the names i've given to the lookup tables to do this.
UPDATE downloads
SET downloads.user_id = users.user_id
, downloads.item_id = items.items_id
FROM downloads
INNER JOIN import_users ON downloads.user_id = import_users.import_user_id
INNER JOIN import_items ON downloads.item_id = import_items.import_item_id
Either way (lookup is in DB, or it's derived from code), would it not just be easier to insert the information correctly in the first place? this would mean you can't have any FK's on your table since sometimes they point to one table, and others they point to another. seems a bit odd.