SQL Server query to get the difference between two dates in two different columns - sql

I would like to write a SQL Server query which should get the difference between two dates (i.e. dates are available in two columns named "Start date" and "End date"). I would like to find the difference between two dates in these two different columns and update in another column as "Expired" if the difference is -1 or below. Most importantly: The time should start from the specified start date and it should check periodically.

To find the differential between two date values you use the DATEDIFF() function.
Also, depending on your requirements, you can set this up in your table as a Computed Column. That way any changes to the component columns in the computed column's definition will automatically update the computed column to reflect the new values.
With the PERSISTED keyword you can also allow the computed column to be indexed on.
Check the documentation here for more details: https://technet.microsoft.com/en-us/library/ms191250%28v=sql.105%29.aspx

This is based on what I think you are trying to do, it's not exactly clear.
I don't think you want to add a column to your table to identify what is expired because that column would be dependant on the "End Date" column as well as the primary key which would violate the 3rd normal form. It really shouldn't be needed because you can query out which ones are expired at any time. I can't really think of a scenario where you would need to have a column that indicates expiry. You can create a query like others mentioned to display (not create) another column that marks the expired rows, or you can simply display only the ones expired, or it might make more sense to move them to a different table.
SET IDENTITY_INSERT ExpiredTableName ON
INSERT INTO ExpiredTableName (Column1, Column2, StartDate, EndDate)
SELECT *
FROM TableName
WHERE DATEDIFF(day, InvoiceDate, '2015-04-20') >0
Identity Insert is for auto-generated keys only.
You can run your queries at regular time intervals like was already mentioned.

You can use DATEDIFF and case when like this:
update table set expColumn = case when DATEDIFF(day,start_date,end_date) > 0
then 'Expired' end FROM table
Hope this helps.

Related

How to add column to an existing table and calculate the value

Table info:
I want to add new column and calculated the different of the alarmTime column with this code:
ALTER TABLE [DIALinkDataCenter].[dbo].[DIAL_deviceHistoryAlarm]
ADD dif AS (DATEDIFF(HOUR, LAG((alarmTime)) OVER (ORDER BY (alarmTime)), (alarmTime)));
How to add the calculation on the table? Because always there's error like this:
Windowed functions can only appear in the SELECT or ORDER BY clauses.
You are using the syntax for a generated virtual column that shows a calculated value (ADD columnname AS expression).
This, however, only works on values found in the same row. You cannot have a generated column that looks at other rows.
If you consider now to create a normal column and fill it with calculated values, this is something you shouldn't do. Don't store values redundantly. You can always get the difference in an ad-hoc query. If you store this redundantly instead, you will have to consider this in every insert, update, and delete. And if at some time you find rows where the difference doesn't match the time values, which column holds the correct value then and which the incorrect one? alarmtime or dif? You won't be able to tell.
What you can do instead is create a view for convenience:
create view v_dial_devicehistoryalarm as
select
dha.*,
datediff(hour, lag(alarmtime) over (order by alarmtime), alarmtime) as dif
from dial_devicehistoryalarm dha;
Demo: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=b7f9b5eef33e72955c7f135952ef55b5
Remember though, that your view will probably read and sort the whole table everytime you access it. If you query only a certain time range, it will be faster hence to calculate the differences in your query instead.

Combine two columns of table into one in SQL

I would like to combine two columns(both from different table) into one column.
As shown below, both are expiry date and I would like them to be combined. Either one column will be present. If one is present, the other will not be present. But at times, both will not be present at the same time. I have looked at concat in sql but it is used to combine.
Need some guidance on this.
If you are using SQL Server can update the blanks in Expiry column as NULLs then you can do this
ISNULL(Expiry,Expiration_date)
Check if the first exists then take it else take the second one: like below:
select if(Expiry!='',Expiry, Expiration_date) as expiry from table

I am trying to add multiple rows in access based on certain criteria

I am new to MS Access and SQL Server and I am trying to learn them.
I have a table that lists certain products with components. There are 4 columns:
PNUM, Component_PNUM, WHS, quantity
I need to do a mass add in component_PNUM to each PNUM that ends with certain criteria. I can use the WHERE clause to filter the correct pnum, but I do not know how to do a mass add to the right products.
Here is a query that will make the [component_PNUM] set to the value Pkg-788812 Pkg-700200 and the [quantity] field set to 1 4.
Please note this query will change the data in your database permanently. Take a backup before running this.
UPDATE table-name
SET [quantity] = '1 4', [component_PNUM] = 'Pkg-788812 Pkg-700200'
However I don't think that is what you are looking for. What this will do is set the quantity to all the same value (and this will not be represented as a numeric value). Also, [component_PNUM] will have the same value for all records.
Best practice is that for each column, there should only be one value for each record. This sounds like both columns will have two values. Also, quantity sounds like it should be a numeric value and in that case, you cannot add two values like 1 and 4. It can only be one numeric value.

How to create a custom primary key using strings and date

I have an order table in sql server and I need for the order number primary key to be like this
OR\20160202\01
OR is just a string
20160202 is the Date
01 is sequence number for that day
for second Order record the same day it would be
OR\20160202\02 and so on..
backlashes should also be included...
Whats the way to go about creating such a field in sql server (using version 2016)
EDIT: to add more context to what sequence number is, its just a way for this field composite or not to be unique. without a sequence number i would get duplicate records in DB because i could have many records the same day so date would remain the same thus it would be something like
OR\20160202 for all rows for that particular day so it would be duplicate. Adding a "sequence" number helps solve this.
The best way is to not create such a column in SQL. You're effectively combining multiple pieces of data into the same column, which shouldn't happen in a relational database for many reasons. A column should hold one piece of data.
Instead, create a composite primary key across all of the necessary columns.
composite pk
order varchar(20)
orDate DateTime
select *
, row_number() over (partition by cast(orDate as Date) order by orDate) as seq
from table
Will leave it to you on how to concatenate the data
That is presentation thing - don't make it a problem for the PK
About "sequence number for that day" (department, year, country, ...).
Almost every time I discussed such a requirement with end users it turned out to be just misunderstanding of how shared database works, a vague attempt to repeat old (separate databases, EXCEL files or even paper work) tricks on shared database.
So i second Tom H and others, first try not to do it.
If nevertheless you must do it, for legal or other unnegotiatable reasons then i hope you are on 2012+. Create SEQUENCE for every day.
Formatted PK is not a good idea.Composite key is a better approach.The combination of day as a date column and order number as a bigint column should be used.This helps in improving the query performance too.
You might want to explore 'Date Dimension' table. Date Dimension is commonly used table in data warehousing. It stores all the days of the calendar(based on your choice of years) and numeric generated keys for these days. Check this post on date dimension. It talks about creating one in SQL SERVER.
https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/

How are these tasks done in SQL?

I have a table, and there is no column which stores a field of when the record/row was added. How can I get the latest entry into this table? There would be two cases in this:
Loop through entire table and get the largest ID, if a numeric ID is being used as the identifier. But this would be very inefficient for a large table.
If a random string is being used as the identifier (which is probably very, very bad practise), then this would require more thinking (I personally have no idea other than my first point above).
If I have one field in each row of my table which is numeric, and I want to add it up to get a total (so row 1 has a field which is 3, row 2 has a field which is 7, I want to add all these up and return the total), how would this be done?
Thanks
1) If the id is incremental, "select max(id) as latest from mytable". If a random string was used, there should still be an incremental numeric primary key in addition. Add it. There is no reason not to have one, and databases are optimized to use such a primary key for relations.
2) "select sum(mynumfield) as total from mytable"
for the last thing use a SUM()
SELECT SUM(OrderPrice) AS OrderTotal FROM Orders
assuming they are all in the same column.
Your first question is a bit unclear, but if you want to know when a row was inserted (or updated), then the only way is to record the time when the insert/update occurs. Typically, you use a DEFAULT constraint for inserts and a trigger for updates.
If you want to know the maximum value (which may not necessarily be the last inserted row) then use MAX, as others have said:
SELECT MAX(SomeColumn) FROM dbo.SomeTable
If the column is indexed, MSSQL does not need to read the whole table to answer this query.
For the second question, just do this:
SELECT SUM(SomeColumn) FROM dbo.SomeTable
You might want to look into some SQL books and tutorials to pick up the basic syntax.