Thanks for such thorough questions, and sorry for all of confusion - commenting 1 year after initial answer is hard and now 3 years after.. initial thoughts fade and confuse me too, but I fear to edit the hole thing because I'm not working on storing notifications on backend right now and not sure if I make good judgements without practical application
I think at the time of writing:
- Yes and no, notificationID was a foreign key, notificationObjectID was not. You do need another FK field to tie tables together. I blame my mongo experience in not being so clear about it :(
- Yes and no, notification_object.object is vague because you can have it just as a string, or something complex (JSON, or FK). In my case it was just a noun.
So it all depends on how your notifications look. For simple case, you just want to link entire notification to some URL, like friends page - thats why having object (entityType) as a string is useful - you tie URLs to it.
Notification "you have 3 friend requests added" can be stored differently.
If you want to show them one at a time - you'll have 3 notifications, 3 notification objects (friend_request) and 3 entries in notification_change that link to specific friend user.
If you want to show one notification - you'll have 1 notification, 1/more objects and 3/more actions. So in this complex case, like «you have 3 friend requests from user A, user B, user C» - you use notificationObjectIDs for each user and have several links in your notification text.
Should you use 1 or 3 friend_request objects? It depends on
- What is the object and what is the action. Is «article liked/commented»? Or is it «like/comment added» and object hierarchy gets linked only during display? Here is facebook distinguishing «photo commenting» from «user mentioning» which semantically seem to be very close — you have same photo, same actor but different notifications that could have been merged together
- Can you remove a notification or do you need a history?
So if I send a friend request and then cancel it, or comment and then delete an article, like and then unlike something - should It show this history (as another action) to the end user as two different actions? Probably not. In addition its techincally more complex - you need to search if there is an existing notification_object, add new notification_change to it (if not - add a new object) so that later I would need to search through notification_change to remove it. Instead I would just add another notification_object to the same notification and remove it if its gone with actions getting cascade-deleted.
On the other hand, there could be cases, where it might be useful to have grouping of actions where nothing gets wiped from the history.
I think thats why at the time of writing, 1:n relation between left and middle tables were done - so that you could group notifications not only by actors on the same entity (middle-right tables) but by several object/entities too.
But sure, you can simplify entire case and optimize storage by reversing left-middle relationship to n:1, so that you have per-user notifications generated for one event.
So that it would it look more like this..
╔═════════════╗ ╔═══════════════════╗ ╔════════════════════╗
║notification ║ ║notification_object║ ║notification_change ║
╟─────────────╢ ╟───────────────────╢ ╟────────────────────╢
║ID ║←—n:1—║ID ║—1:n—→║ID ║
║noteObjFK ║ ║entityType ║ ║noteObjFK ║
║viewerUserID ║ ║entityID ║ ║actionOnEntity ║
╚═════════════╝ ╚═══════════════════╝ ║actorUserID ║
╚════════════════════╝
Hope this helped
When using a query of this form: UPDATE a SET columns=values FROM b WHERE ...
, the b
subquery is evaluated independently of a
, and it's the WHERE block at the end of the query that is supposed to join the rows of a
and b
.
The query in the question attempts to join inside the subquery rather than in a WHERE clause at the uppermost level (in fact it doesn't have such a WHERE clause), but it's not allowed and that's what the error message indicates.
The SQL-standard way of updating each row with a correlated subquery would be:
UPDATE a SET (col1,col2) =
(SELECT val1,val2 FROM b WHERE expression-needing-values-from-a)
but in older versions of PostgreSQL (9.4 or before), the manual explicitly tells that this form is not implemented. Starting with 9.5, it is implemented.
The typical way to emulate it with postgres 9.4 is to use a copy of table a
in the subquery and join back to the updated table in the upper level's WHERE clause, like this:
UPDATE a SET (col1,col2)=(s.col1,s.col2)
FROM (SELECT a2.ctid,col1,col2 AS ctid_of_row FROM b, a AS a2 WHERE...) AS s
WHERE s.ctid_of_row = a.ctid;
knowing that ctid
is the system pseudo-column that indicates the physical location of the row version within its table. Alternatively, the primary key can be used if there is one.
In your case, the transformation is not obvious because your subquery is meant to produce only one row with its ORDER BY... LIMIT 1
at the end. It should be redesigned to produce all the target rows in a single resultset, presumably (verticeid,cost,gid)
where cost
and gid
are determined per offer.verticeid
.
Best Answer
I don't know much of T-SQL but I believe that to compare strings you need the logical operator
AND
. Try this:UPDATE StaffCopy SET StaffCopy.LastName=IIF(([LastName]='Avon' AND [FirstName]='Sarah'), 'Tyne', [LastName]);