SQL update 'target' table to achieve 'result' table using 'source' table - sql

There is a table 'target' that looks like this:
id val
1 A
2 A
3
5 A
8 A
9
There is also a 'source' table that looks like this
id val
1
2 B
4 B
8 B
9 B
The directioins ask to use the 'source' table to transform the 'target' table into the 'result' table, which looks like this:
result
id val
1
2 B
3
5 A
8 B
9 B
I understand the logic of what the question is asking, as I believe what I need to do is basically say
IF target.id = source.id
SET target.val = source.val
ELSE target.val = target.val
However, I am not completely sure how to accomplish this kind of update in SQL based on conditions w/ multiple tables using postgresql.

This looks like homework so I won't give a complete answer.
First step is to turn these into tables you can actually use. A handy tool for this is provided by http://sqlfiddle.com, with its "text to table" feature. Because of the dodgy formatting of the input we've got to make some fixups before it'll work (assuming empty cols are null, not empty string; fixing whitespace errors) but then we get:
http://sqlfiddle.com/#!15/4a046
(SQLfiddle is far from a model of how you should write DDL - it's a useful debugging tool, that's all).
So now you have something to play with.
At this point, I suggest looking into the UPDATE ... FROM statement, which lets you update a join. Or you can use a subquery in UPDATE to perform the required logic.
UPDATE target
SET val = source.val
FROM /* you get to fill this in */
WHERE /* you get to fill this in */
Merging data
Luckily, the result table they've given you is the result of a simple join-update. Note that rows present in "source" but not "target" haven't been added to "result"
If you were instead supposed to merge the two, so that entries in source that do not exist in target at all get added to target, this becomes what's called an upsert. This has been written about extensively; see links included in this post. Be glad you don't have to deal with that.

Related

How to UPDATE from a Select in sql?

A little personal project i'm doing, kinda new in sql.
Lets say i have a table with multiples columns, but i want to work with 2 for this request: CODE and VALUE
Basically, the codes are like this : 1_A, 1_B, 1_C, 2_A, 2_B, 2_C, 3_A, 3_B, 3_C, etc... They are already created.
What i want to do is replace the VALUE from the C codes with the A codes: 1_A -> 1_C, 2_A->2_C, and so on. Without touching the other colmuns
What i thougt so far is :
update TABLE set Value = (select value from TABLE from CODE like '%A%') where CODE like '%C%'
But how do make sure that the Value associated with the code X_A gets copied into X_C specifically ? Like, so 1_A gets copied into 1_C and not 2_C. Maybe it has to do with JOIN, but honestly i don't get how those work yet
Edit : it's on oracle
If you're looking to copy all the A values to C values, you should use an insert statement, not an update statement. This can be with the insert-select construct:
INSERT INTO mytbale (value)
SELECT REPLACE(value, 'A', 'C')
FROM mytable
WHERE value LIKE '%A'

How to use the like function to delete the table record?

I have a problem to use the like % function to delete the table record, it cannot follow the 299-1_B to delete the row in the table.
I am used below the sample code to delete:
DELETE FROM filing_code_management WHERE folder_location LIKE '299-1_B%'
table structure
no|folder_location
-- ------------------------------------
1 299_A/299-1_B/299-1-1_C/299-1-1-1_D
2 299_A/299-1_B
3 300_B/300-1_C
3 299_A/299-1_B/299-1-1_C/299-1-1-2_F
4 299_A/299-1_B/299-1-2_P/299-1-2-1_Q
If success to show the result, the result just show 300_B/300-1_C record. Hope someone can guide me which part I am getting wrong.
Please use below query,
DELETE FROM filing_code_management WHERE folder_location LIKE '%299-1_B%'
I think you want to find the pattern anywhere in the string:
folder_location LIKE '%299-1_B%'
Or perhaps:
folder_location LIKE '299-1_B%' OR folder_location LIKE '%/299-1_B%'
That said, you appear to be storing multiple values in a string. That is bad, bad, bad. You should have a separate table with one row per folder location, rather than forcing all of them into a single string.

Dealing with multiple output results in UPSERT query [SQL]

I'm trying to do an update query in which a single row the table is updated and, if nothing has matched and updated, a new row is inserted. In each case, I need the query to return the ID of the inserted row.
The issue I'm having is this query is returning 2 separate results when the insert case is reached, one for each output (the first empty, the second containing the ID). I'm running this query using SQL Alchemy on python and I'm only able to see the first result, which is empty.
UPDATE [Rights]
SET accessLevel = :access_level
OUTPUT inserted.rightsID
WHERE principal = :principal and [function] = :function
IF ##ROWCOUNT = 0
INSERT INTO Rights(principal, [function], accessLevel)
OUTPUT inserted.rightsID
VALUES(:principal, :function, :access_level)
And I'm calling it like so:
inserted_right_id = session.execute(sql_rights_update, right).fetchall()
Can anyone recommend a way of changing the query so that I can still use the UPSERT method, but only receive one of the IDs? I was considering storing the OUTPUT values into a table and returning that, or wrapping the whole thing in a select but hopefully there's something more elegant out there.
Thanks a million.
Feeling quite dumb. I simply added a
IF EXISTS(SELECT * FROM Rights WHERE principal = :principal and [function] = :function)
UPDATE ...
ELSE
INSERT ...

Create column name based on value without execute

I need to create a column name based on the value of other columns. I need to return a value from a column, but the specific name depends on the value insert on other table.
From intance:
Table A
Column1 | Column2
1 2
Base on that values I need to go to the table B to the column "VE12".
I need this dynamiclly, so the execute(#query) is my last option and I would like to avoid CASE WHEN statments because I have more than 50 options.
My query will be something like:
select case when fn.tab=8 and fo.pais=3 then cp.ve83 end
FROM fn
INNER JOIN fo ON fo.stamp = fn.stamp
INNER JOIN cp
If the value in the column tab is 8 and the value in column pais is 3 I should return the value in column ve83.
Thanks for all the help!
The only sensible option is to go back to the business meaning of the data and redesign the database according to that, instead of according to "technique-oriented abstractions" such as these that SQL was never intended to support.
The main reason for this is that SQL was founded on FIRST order logic, and this precludes supporting stuff like varying domains. Which you are doing (or at least seeking to do) because ve12 could be a DATETIME and ve83 could be a VARCHAR and ve56 coulb be a BLOB etc. etc. So there is just no way for you [or anyone else] to determine the data type of the results in your query, and it is even more impossible to attach meaning to what comes out of your desired query precisely because of this varying-domain and varying-source characteristic.

Structuring many update statements in SQL Server

I'm using SQL Server. I'm also relatively new to writing SQL... in a strong way. It's mostly self-taught, so I'm probably missing key ideas in terms of proper format.
I've a table called 'SiteResources' and a table called 'ResourceKeys'. SiteResources has an integer that corresponds to the placement of a string ('siteid') and a 'resourceid' which is an integer id that corresponds to 'resourceid' in ResourceKeys. ResourceKeys also contains a string for each key it contains ('resourcemessage'). Basically, these two tables are responsible for representing how strings are stored and displayed on a web page.
The best way to consistently update these two tables, is what? Let's say I have 5000 rows in SiteResources and 1000 rows in ResourceKeys. I could have an excel sheet, or a small program, which generates 5000 singular update statements, like:
update SiteResources set resoruceid = 0
WHERE siteid IS NULL AND resourceid IN (select resourceid
from ResourceKeys where resourcemessage LIKE 'FooBar')
I could have thousands of those singular update statements, with FooBar representing each string in the database I might want to change at once, but isn't there a cleaner way to write such a massive number of update statements? From what I understand, I should be wrapping all of my statements in begin/end/go too, just in-case of failure - which leads me to believe there is a more systematic way of writing these update statements? Is my hunch correct? Or is the way I'm going about this correct / ideal? I could change the structure of my tables, I suppose, or the structure of how I store data - that might simplify things - but let's just say I can't do that, in this instance.
As far as I understand, you just need to update everything in table SiteResources with empty parameter 'placement of a string'. If so, here is the code:
UPDATE a
SET resourceid = 0
FROM SiteResources a
WHERE EXISTS (select * from ResourceKeys b where a.resourceid = b.resourceid)
AND a.siteid IS NULL
For some specific things like 'FooBar'-rows you can add it like this:
UPDATE a
SET resourceid = 0
FROM SiteResources a
WHERE EXISTS (select * from ResourceKeys b where a.resourceid = b.resourceid and b.resourcemessage IN ('FooBar', 'FooBar2', 'FooBar3', ...))
AND a.siteid IS NULL
Let me see if I understood the question correctly. You'd like to update resourceid to 0 if the resourcemessage corresponds to a list of strings ? If so, you can build your query like this.
UPDATE r
SET resourceid = 0
FROM SiteResources r
JOIN ResourceKeys k ON r.resourceid = k.resourceid
WHERE k.resourcemessage IN ('FooBar', ...)
AND r.siteid IS NULL;
This is using an extended UPDATE syntax in transact-sql allowing you to use a JOIN in the UPDATE statement. But maybe it's not exactly what you want ? Why do you use the LIKE operator in your query, without wildcard (%) ?
With table-valued parameters, you can pass a table from your client app to the SQL batch that your app submits for execution. You can use this to pass a list of all the strings you need to update to a single UPDATE that updates all rows at once.
That way you don't have to worry about all of your concerns: the number of updates, transactional atomicitty, error handling. As a bonus, performance will be improved.
I recommend that you do a bit of research what TVPs are and how they are used.