How to order feeds by their latest item contained? - sql

I am trying to create "feeds" in SQL that contain "items", and when I am getting all the feeds (SELECT * FROM Feeds), I want to order them by when they were last updated (the last time an item was added to the feed). The "item" has a publish date column.
So far my query looks like this:
SELECT
F.FeedID,
F.Title,
F.Link,
F.Language,
F.Copyright,
F.Subtitle,
F.Author,
F.Summary,
F.OwnerName,
F.OwnerEmail,
F.ImageURL,
F.Category
FROM Feeds F
LEFT JOIN Items I
ON F.FeedID = I.FeedID
ORDER BY I.PublishDate DESC
Somehow I want to order the "items" joined on so that the most recent item is joined on with that feed. Is this possible? Or should I just add a "last updated" column to the "feeds" table?

You need to add a last updated column of type DateTime, and set the value appropriately when inserting or updating rows, as your needs dictate. That is to say, set its value depending on whether you want the most recently updated item or the item which was most recently added (updated versus inserted), as they may differ. You can then order by this new column.
You cannot use order by on the data as shown to find the last modified item, as publish date is (almost certainly) the date the book was published, not the date the row was added to the database.

Date created and date updated are very important things to track in a database.
A ERD (entity relationship diagram) shows how the database is laid out.
http://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model
The details of both tables will help in clearing up what you are trying to accomplish.

Related

Find original value for record using temporal and history table

In SQL Server, if you have a temporal table and a history table, how do you find the original values for a record if you do not know the date/time that record was first created?
If the record was never edited, then it won't have a value in the history table and the original record is in the temporal table.
If it was edited, the original record is in the history table but with valid_from and valid_to dates that you don't know.
Is there a parameter in the FOR SYSTEM_TIME clause that returns the record as it appeared when it was first added to the table, regardless of whether it has changed since?
Just one note on the answer. You mention this :
If the record was never edited, then it won't have a value in the history table and the original record is in the temporal table. If it was edited, the original record is in the history table
A huge benefit of using Temporal Tables is that it acts as a single table. It is not two tables where you have to do unions to work out which table you should be looking at. If you were creating a history table manually (e.g. A roll your own audit solution), then you would have to query across two different tables.
Now onto your solution. The easiest way would be to use the SYSTEM_TIME ALL flag. It works like so :
SELECT TOP 1 *
FROM Person
FOR SYSTEM_TIME ALL
WHERE Id = 1
ORDER BY ValidFrom ASC
This returns ALL historic records for a particular ID. But because we order by ValidFrom and then select the TOP 1, we actually return the very first entry.
And again, this works regardless of whether that first record is in the "current" table or the history table.
More info here : https://dotnetcoretutorials.com/2021/12/11/temporal-tables-in-sql-server/

SQL : How to pull all instances of an ID if one has changed based on change date?

Select *
From OrderTable
Where CAST(lastActivity AS Date) = CAST(GETDATE() AS Date)
Above is what I am using right now. But I realized that if there has been a change to an order I would need to grab all instances of that OrderID not just the line where something was updated.
So for example, one order can have multiple items. Lets say 5, so in the Ordertable there are 5 rows with the same OrderID. If someone went back and changed something for one item the last activity date for that item row will be updated to today and then it will be pulled. But I want to be able to pull the entire Order if there is change in one item, (i.e pull all 5 instances of OrderID if one of the items has been changed). The itemid's are unique to an order just an fyi.

How to efficiently query one table to obtain a value I need to then change two dates on two rows in another table?

I get the feeling this is easy for SQL, but I'm new to it. I want to query table CUST_TRAN and find out the ID for value $1 which is in column INVOICE.
I then want to use the newly discovered ID to update table TRANSACTS to change the DATE and DATE_TIME (two values in two columns) to value $2 using the column IDFROMTRAN to match the ID against. There are very often two rows with the same IDFROMTRAN that need to be updated, because the customer signs for the goods and that creates its own row.
Does any of this make sense?
Basically, to explain what I'm doing I'm changing the date on transactions to put them into last month, so that they'll be invoiced correctly and reflect when the customer was actually in store.
TLDR: How do I find out an alternative ID for a transaction then use that to change the date in two rows in another table?

SQL Server Reference/Lookup Tables and Updates

I have two SQL tables: TableA and LookupTable. TableA stores LookupTableID (PK) as a foreign key and some other fields. The LookupTable stores LookupTableID, PharmacyName, PharmacyAddress, PostCode, PharmacyTelephone, PharmacyFax, PharmacyEmail etc.
The data from TableA is displayed in an Asp.net form. The form has two buttons for each row of the grid: Print button and Preview button. When user clicks Print button, a pdf document containing the pharmacy information from LookupTable (for LookupTableID in TableA) along with some other information from TableA is produced in the document. Moreover, the Printed field in TableA is set to true, and a new record in TableA is created, the only difference between the printed and the newly created record is in the following fields: StartDate, EndDate and Printed. In the newly created record, StartDate becomes "EndDate from printed record + 1 Day", EndDate becomes "EndDate from printed record + 7 days", and Printed is false for the newly created record.
When user clicks Preview button, a pdf document containing the pharmacy information from LookupTable (for LookupTableID in TableA) along with some other information from TableA is produced in the document. Note that the system doesn't create a new record or set printed to true in this case.
The issue that I have with above database design is: if one of the columns lets say PostCode in the Lookup Table is amended and user clicks on Preview button for historical/printed records then the preview pdf document will display up to date information i.e. new post code rather than the post code at the time of the printing. I know, this is an expected behaviour. However, I would like to display the information for historical records as they were printed, and the up to date information for only those records which are not yet printed.
One work around that I have is to treat LookupTable as a library table for the user to select a pharmacy and then copy everything (all fields from the lookup table) across to the TableA for the selected pharmacy. This will create a lot of duplicate data in the database. Is there a better way to achieve my objective? Any help would be appreciated.
This seems like a needlessly complicated and inflexible way of taking a snapshot of your data every time it is printed. It would seem like a much better alternative would be to version both tables and create a third table which would just contain the TableA ID and the date it was printed. There is no need to make a copy of the data. To reproduce the data as it was on the date of any particular print, just use the print date to query the versioned data as of that date. You would get back the data as it appeared on that date, no matter how much it changed since then.
One answer I have given for a similar situation is here:
https://dba.stackexchange.com/questions/114580/best-way-to-design-a-database-and-table-to-keep-records-of-changes/114738#114738
Hope it helps.
For historical data there are (at least) two approaches:
You store your information with a ValidUntil date. The one with a NULL is the current.
Older data can be found with something similar to:
DECLARE #test TABLE(id INT,ValidUntil DATETIME);
INSERT INTO #test VALUES(1,{d'2015-01-01'})
,(2,{d'2015-02-01'})
,(3,{d'2015-03-01'})
,(4,NULL);
DECLARE #ValidOn DATETIME={d'2015-01-02'}; --set any value you like, even NULL
WITH HelperDates AS
(
SELECT ISNULL(#ValidOn,GETDATE()) AS ValidOn
,(SELECT MAX(ValidUntil) FROM #test) AS MaxDate
)
SELECT TOP 1 tbl.*
FROM #test AS tbl
CROSS JOIN HelperDates AS hd
WHERE hd.MaxDate IS NULL OR hd.ValidOn > hd.MaxDate OR hd.ValidOn <= tbl.ValidUntil
ORDER BY tbl.ValidUntil ASC
Especially with out-prints I'd prefer this way
Store the necessary data in the moment of creation of your document. Best in my eyes is an XML column together with the created document.
Good luck in finding the best approach!

MS Access - Log daily totals of query in new table

I have an ODBC database that I've linked to an Access table. I've been using Access to generate some custom queries/reports.
However, this ODBC database changes frequently and I'm trying to discover where the discrepancy is coming from. (hundreds of thousands of records to go through, but I can easily filter it down into what I'm concerned about)
Right now I've been manually pulling the data each day, exporting to Excel, counting the totals for each category I want to track, and logging in another Excel file.
I'd rather automate this in Access if possible, but haven't been able to get my heard around it yet.
I've already linked the ODBC databases I'm concerned with, and can generate the query I want to generate.
What I'm struggling with is how to capture this daily and then log that total so I can trend it over a given time period.
If it the data was constant, this would be easy for me to understand/do. However, the data can change daily.
EX: This is a database of work orders. Work orders(which are basically my primary key) are assigned to different departments. A single work order can belong to many different departments and have multiple tasks/holds/actions tied to it.
Work Order 0237153-03 could be assigned to Department A today, but then could be reassigned to Department B tomorrow.
These work orders also have "ranking codes" such as Priority A, B, C. These too can be changed at any given time. Today Work Order 0237153-03 could be priority A, but tomorrow someone may decide that it should actually be Priority B.
This is why I want to capture all available data each day (The new work orders that have come in overnight, and all the old work orders that may have had changes made to them), count the totals of the different fields I'm concerned about, then log this data.
Then repeat this everyday.
the question you ask is very vague so here is a general answer.
You are counting the items you get from a database table.
It may be that you don't need to actually count them every day, but if the table in the database stores all the data for every day, you simply need to create a query to count the items that are in the table for every day that is stored in the table.
You are right that this would be best done in access.
You might not have the "log the counts in another table" though.
It seems you are quite new to access so you might benefit form these links videos numbered 61, 70 here and also video 7 here
These will help or buy a book / use web resources.
PART2.
If you have to bodge it because you can't get the ODBC database to use triggers/data macros to log a history you could store a history yourself like this.... BUT you have to do it EVERY day.
0 On day 1 take a full copy of the ODBC data as YOURTABLE. Add a field "dump Number" and set it all to 1.
1. Link to the ODBC data every day.
join from YOURTABLE to the ODBC table and find any records that have changed (ie test just the fields you want to monitor and if any of them have changed...).
Append these changed records to YOURTABLE with a new value for "dump number of 2" This MUST always increment!
You can now write SQL to get the most recent record for each primary key.
SELECT *
FROM Mytable
WHERE
(
SELECT PrimaryKeyFields, MAX(DumpNumber) AS MAXDumpNumber
FROM Mytable
GROUP BY PrimaryKeyFields
) AS T1
ON t1.PrimaryKeyFields = Mytable.PrimaryKeyFields
AND t1.MAXDumpNumber= Mytable.DumpNumber
You can compare the most recent records with any previous records.
ie to get the previous dump
Note that this will NOT work in the abvoe SQL (unless you always keep every record!)
AND t1.MAXDumpNumber-1 = Mytable.DumpNumber
Use something like this to get the previous row:
SELECT *
FROM Mytable
INNER JOIN
(
SELECT PrimaryKeyFields
, MAX(DumpNumber) AS MAXDumpNumber
FROM Mytable
INNER JOIN
(
SELECT PrimaryKeyFields
, MAX(DumpNumber) AS MAXDumpNumber
FROM Mytable
GROUP BY PrimaryKeyFields
) AS TabLatest
ON TabLatest.PrimaryKeyFields = Mytable.PrimaryKeyFields
AND
TabLatest.MAXDumpNumber <> Mytable.DumpNumber
-- Note that the <> is VERY important
GROUP BY PrimaryKeyFields
) AS T1
ON t1.PrimaryKeyFields = Mytable.PrimaryKeyFields
AND t1.MAXDumpNumber= Mytable.DumpNumber
Create 4 and 5 and MS Access named queries (or SS views) and then treate them like tables to do comparison.
Make sure you have indexes created on the PK fields and the DumpNumber and they shoudl be unique - this will speed things up....
Finish it in time for christmas... and flag this as an answer!