SQL update for multiple database entries - sql

we are using a commercial application, which is customizable. Front End is a webserver with MS SQL server in background.
We have an asset management, which with we can link some contracts.
Now I have to create a new workflow: An asset has a costcenter and all linked contracts to this object have to migrate the costcenter dialy night automatically.
For example that's my view "View_Info" to get needed information:
IDAsset - IDContract - ConstCenterAsset
111 222 333
111 223 333
112 224 334
113 225 335
....
And my main table "Contract":
ID - CostCenter
222 000
223 000
224 000
225 000
I know how to update one entry in "Contract" table with SQL UPDATE command...
But how can I do it for all existing entries...
I have to update about 1000 DB entries dialy night...

You can UPDATE with JOIN like this:
UPDATE c
SET c.CostCenter = v.ConstCenterAsset
FROM Contract as c
INNER JOIN View_Info as v ON v.IDContract = c.ID;
This way, all the table Contract' entries will be updated from the view View_Info. You can also add extra WHERE clause at the end to limit the entries which should be updated.

Related

How to write a query to return only specified list of rows?

There is a table Shops with Shop_number and Shop Address columns.
Also a table called Properties with two columns:
Shop_number
Property_ID
222222
113
222222
114
222222
115
222223
113
222224
113
222225
111
222226
112
A shop can have more than one property.
How to write a query which would return all shop numbers which does not have Property_ID: 113 at all (excluding 222222, because it indeed has other properties, but also 113).
SELECT p.shop_number FROM Properties p
WHERE p.property_id != 113
My query returns also store 222222 which has 113 property_id.
I would like to return shop numbers: 222225 and 222226 in this case only.
Your description is a bit unclear.
Since you already got an answer how to get your result in case you have to use one of the two tables only, let's have a look on your requirements again which can be read as you need both tables.
You are writing: "A shop can have more than one property. How to write a query which would return all shop numbers which does not have Property_ID: 113 at all"
I don't know if this is your intention, but according to your description, you also want to get all shops that don't even occur at all in the properties table.
So we could use such a query:
SELECT s.shop_number
FROM shops s
WHERE NOT EXISTS
(SELECT 1 FROM properties WHERE property_id = 113
AND shop_number=s.shop_number);
This will show all shop numbers that don't appear at all in the properties table and also all shop numbers that appear having properties different from 113 only.
Only those shop_numbers that occur in the properties table and exist there having the property id 113 will be excluded.
And this is exactly what you described as being your requirement. It's the question if what you told us you want to do is really what you want to do ;)
Either use not exists as #Larnu suggests or use group by / having:
select shopnumber
from t
group by shopnumber
having count(case property_id when 113 then 1 end) = 0;
case maps property_id = 113 to 1 and everything else to null. count(x) does not count rows where x is null.

SQL UPDATE SET interchanges values

I update a View to get in two columns the same value, but it interchanges the two values instead of just setting it. My (reduced for so) view UpdateADAuftrag2 is this.
SELECT dbo.CSDokument.AD1, dbo.UpdateAS400zuSellingBenutzer2.BenutzerNr
FROM dbo.AS400Auftrag
INNER JOIN
dbo.CSDokument ON dbo.AS400Auftrag.Angebotsnummer = dbo.CSDokument.Angebotsnummer
INNER JOIN
dbo.UpdateAS400zuSellingBenutzer2 ON dbo.AS400Auftrag.AD = dbo.UpdateAS400zuSellingBenutzer2.SchluesselWert
AND
dbo.CSDokument.AD1 <> dbo.UpdateAS400zuSellingBenutzer2.BenutzerNr
WHERE (dbo.AS400Auftrag.AD IS NOT NULL)
The important part is dbo.CSDokument.AD1 <> dbo.UpdateAS400zuSellingBenutzer2.BenutzerNr
AD1 is user number for external workers and BenutzerNr means user number. So e.g. the person Charlie Brown is an external worker and has the user number 31. When in AD1 is 31 - Charlie Brown is the external worker for this document (order in this case).
The Update statement loos like this
UPDATE [dbo].[UpdateADAuftrag2]
SET [AD1] = [BenutzerNr]
I have for example these values
AD1 | BenutzerNr
31 | 54
99 | 384
112 | 93
after the update the result is this
AD1 | BenutzerNr
54 | 31
384 | 99
93 | 112
Why not this?
AD1 | BenutzerNr
54 | 54
384 | 384
93 | 93
edit: UpdateAS400zuSellingBenutzer is also a View, but as far as I can see it includes only BenutzerNr and not AD1.
Firstly, you're never going to see your expected results in the view. Your UPDATE statement is effectively a DELETE statement (as far as the view is concerned). Rows only appear in the view if AD1 <> BenutzerNr, but you're setting them to be equal.
However, the documentation for updatable views states "Any modifications, including UPDATE, INSERT, and DELETE statements, must reference columns from only one base table." Your update statement references columns from more than one table.
https://msdn.microsoft.com/en-us/library/ms187956.aspx#Updatable Views
I'm not sure what you're trying to achieve here, but in my experience it's usually easier to issue the UPDATE statement against the base tables directly.
There were 2 bugs - Bug 1 View UpdateAS400zuSellingBenutzer2 had 2 results sometimes for one entry in CSDokument and Bug 2 There were 2 entries in Table AS400Auftrag and then it switched between these two entries. So it just looked like the SET switched the two entries but it was just by chance. Thanks for reading.

Updating a column in postgresql based on a specific date

I'm wondering if I could use trigger with PostgrSQL to update a column where I do have column with date type and on this date I would like to updated another column in another table.
To make it more clear
I do have 2 tables
Works_locations table
walphid wnumberid locationid
DRAR 1012 101
PAPR 1013 105
PAHF 1014 105
ETAR 1007 102
DRWS 1007 102
the locationsid attribute refers to "locid' in Locations table which is down
locid locname
101 Storage
102 Gallary A
103 Gallary B
104 Gallary C
105 Lobby
Exhibition table
exhid exhname description strtdate endDate
101 Famous Blah Blah 2013-07-15 2013-10-13
and here are bridge table to connect the exhibition table with the locations table
locationsid exhibitid
102 102
103 101
104 103
Now Each exhibition has some works and should be placed in one of the locations table.
On the 'endDate' column in the exhibition table, which is a date data type, I would like to update 'locationid' column in the Works locations table to be placed in another location.
In another words. Each exhibitions has some works and this works are placed in one of the locations. at the ending date of the exhibition, I would like to change the locations, and specifically, I would like the work to be returned to the storage.
Any idea how would I do this action with postgresql?
Regard
PostgreSQL does not have a built-in task scheduler. Even if there was a scheduler, the commands it ran wouldn't be triggers, they'd just be be procedures run by a scheduler.
You can't write triggers that fire at some arbitrary time.
You will need to use cron, Task Scheduler, PgAgent, or similar to run the statements at the desired time. Or you could write a script that checks when the next event is, sleeps until then, runs the desired command and marks that event as done, and sleeps until the next event.

Comparing data in same table SQL

Table: working_history
ID Field Event_dt Data
145 Reason 10/20/2003 DOM
145 Reason 9/20/2007 LVE
145 Reason 3/17/2008 RTN
145 Reason 4/5/2008 POP
145 Reason 3/7/2009 POP
145 Reason 6/13/2009 TRE
145 status 10/20/2003 A
145 status 6/5/2006 L
145 status 11/27/2006 A
145 status 9/20/2007 L
145 status 3/17/2008 A
145 status 6/12/2009 T
I want anyone who had an ESTA=L, and then check to make sure that their respective Reason event_dt match Status event_dt. In the above table,
145 status 6/5/2006 L
should come back, as event_dt (6/5/2006) for field.status = L, does not have a data where Field = reason on the same date.
SELECT *
FROM working_History WHReason
RIGHT JOIN Working_history WHStatus
on WHReason.ID = WHStatus.ID
and WHReason.field = 'Reason'
and WHStatus.field = 'status' and WHStatus.Data='L'
and WHReason.Event_DT = WHStatus.Event_DT
WHERE WHReason.Event_Date is null
Assuming you're only looking for status's that do NOT have a reason and not the other way.
This basically says, create two sets of information one for fields of reason one for fields of status. Then combine those two results based on their ID and event date including all records from the status set and only those that match in reason. Limit that result to only include those that have no reason event date.
It uses a concept called a Self Join to generate two sets of data allowing one to quickly identify information in one set but not the other. Visual reference

Compare 2 values of different types inside of subquery

I am using a MS SQL db and I have 3 tables: 'base_info', 'messages', 'config'
bases:
ID Name NameNum
====================================
1 Home 101
2 Castle 102
3 Car 103
messages:
ID Signal RecBy HQ
============================
111 120 Home 1
111 110 Castle 1
111 125 Car 1
222 120 Home 2
222 125 Castle 2
222 130 Car 2
333 100 Home 1
333 110 Car 2
config:
ID SignalRec SignalOut RecBy HQ
====================================
111 60 45 101 1
111 40 60 102 1
222 50 60 102 2
222 30 90 101 2
333 80 10 103 1
Ok so now I have a subquery in which I select the 'SignalRec' and 'SignalOut' from the config table and match it on the messages table by ID and Date(not included above), the problem is that I need it to match where messages.RecBy = config.RecBy but config.RecBy is a string but it's equivalent Name is in the bases table. So I almost need to do a subquery inside a subquery or some type of join and compare the returned value.
Here is what I have so far:
(SELECT TOP 1 config.SignalRec from config WHERE config.ID = messages.ID AND ||I need th other comparison here||...Order By...) As cfgSignalRec,
(SELECT TOP 1 config.SignalOut from config WHERE config.ID = messages.ID AND ||I need th other comparison here||...Order By...) As cfgSignalOut
I tried to make this as clear as possible but if you need more info let me know.
I would normalize out RecBy in your messages table to reference the bases table. Why would you insert the string content there if it's also referenced in bases?
This is exactly why normalization exists: reduce redundancy, reduce ambiguity, and enforce referential integrity.
To make this more clear, RecBy in the messages table should be a foreign key to Bases.
I think this could do the trick (although I have not tried it...)
SELECT
c.SignalRec
FROM config c
INNER JOIN bases b
ON c.RecBy = b.NameNum
INNER JOIN messages m
ON b.Name = m.RecBy
WHERE c.ID = m.ID
However, as Anthony pointed out, you probably want to normalize out the strings in the RecBy column in the messages table, as you have the same data in the bases table.
From your description, it just sounds like you need two JOINS
SELECT TOP 1
c.SignalRec
FROM
config c
INNER JOIN
bases b
ON c.RecBy = b.NameNum
INNER JOIN
messages m
ON b.Name = m.RecBy
I think I might have not been clear enough what I wanted to do, sorry about that.
The data is actually different in the 2 tables, although the correlations are the same. It's kind of confusing to explain without going into detail about how the system works.
I actually found a very fast way of doing this.
Inside my sub-query I do this:
(SELECT TOP 1 config.Signal FROM config,bases
WHERE config.ID = messages.ID AND bases.Name = messages.RecBy AND bases.NameNum =
config.RecBy Order By...)
So this essentially compares the 2 RecBy's of different tables even though one is an integer and the other is a string. It reminds me of a match and look up in Excel.