Create table with condition - sql

I'm creating a table, which will have a date in one of two columns, or neither.
I'd like the third to auto populate with one of these values, without using an update.
CREATE TABLE [table1]
(
id [BIGINT] NOT NULL,
[date1] [DATETIME] NULL,
[date2] [DATETIME] NULL,
[date] AS (CASE
WHEN [date1] IS NOT NULL THEN [date1]
WHEN [date2] IS NOT NULL THEN [date2]
ELSE NULL
END)
)
This doesn't seem to work when I test using:
INSERT INTO [table1] (id, date1)
VALUES (1, GETDATE())
Can anyone help?

Your code appears to be fine, as seen in this db<>fiddle. However, I would suggest using COALESCE() instead of CASE:
CREATE TABLE [table1] (
id [bigint] NOT NULL,
[date1] [datetime] NULL,
[date2] [datetime] NULL,
[date] AS ( COALESCE(date1, date2) )
);
It is more concise.

Related

SQL Server - Operand type clash: numeric is incompatible with datetimeoffset

i am having issue with passing the data from one table to another due to data type.
I tried converting datetimeoffset into date, and inserting into table where i have it as date type and im still getting this error.
this is the format of date/time i have:
2018-12-12 13:00:00 -05:00 in one table, and i have to just pars time and insert it into new table. I tried with casting using ,
CAST([from] AS date) DATE_FROM
I can run the query as select and it works but the moment i try to insert the data into other table even if the other table is formatted and prepared as date type i still get the issue.
Here is the table that stored data with datetimeoffset:
[dbo].[tmp_count](
[elements_Id] [numeric](20, 0) NULL,
[content_Id] [numeric](20, 0) NULL,
[element_Id] [numeric](20, 0) NULL,
[element-name] [nvarchar](255) NULL,
[sensor-type] [nvarchar](255) NULL,
[data-type] [nvarchar](255) NULL,
[from] [datetimeoffset](0) NULL,
[to] [datetimeoffset](0) NULL,
[measurements_Id] [numeric](20, 0) NULL,
[measurement_Id] [numeric](20, 0) NULL,
[from (1)] [datetimeoffset](0) NULL,
[to (1)] [datetimeoffset](0) NULL,
[values_Id] [numeric](20, 0) NULL,
[label] [nvarchar](255) NULL,
[text] [tinyint] NULL
And I am trying to cast columns with datetimeoffset to date and time and push it to #tmp1 table with
SELECT [elements_Id]
,[content_Id]
,[element_Id]
,[element-name]
,[sensor-type]
,[data-type]
,CAST([from] AS date) DATE_FROM
,[to]
,[measurements_Id]
,[measurement_Id]
,CAST([from (1)] AS time (0)) TIME_FROM
,CAST([to (1)] AS TIME(0)) TIME_TO
,[values_Id]
,[label]
,[text]
INTO #Tmp1
FROM [VHA].[dbo].[tmp_count]
SELECT
FROM #tmp1
which gives me the time in format for DATE_FROM as 2018-12-12 and for the DATE_FROM and DATE_TO as 13:00:00 which is exactly what i need.
Now i am trying to splice this table with another table and push it in final table that looks like this:
[dbo].[tbl_ALL_DATA_N](
[serial-number] [nvarchar](255) NULL,
[ip-address] [nvarchar](255) NULL,
[name] [nvarchar](255) NULL,
[group] [nvarchar](255) NULL,
[device-type] [nvarchar](255) NULL,
[elements_Id] [numeric](20, 0) NULL,
[content_Id] [numeric](20, 0) NULL,
[element_Id] [numeric](20, 0) NULL,
[element-name] [nvarchar](255) NULL,
[sensor-type] [nvarchar](255) NULL,
[data-type] [nvarchar](255) NULL,
[DATE_FROM] [date] NULL,
[to] [datetimeoffset](0) NULL,
[measurements_Id] [numeric](20, 0) NULL,
[measurement_Id] [numeric](20, 0) NULL,
[TIME_FROM] [time](0) NULL,
[TIME_TO] [time](0) NULL,
[values_Id] [numeric](20, 0) NULL,
[label] [nvarchar](255) NULL,
[text] [tinyint] NULL
using query below:
INSERT INTO [dbo].[tbl_ALL_DATA_N]
([serial-number],
[ip-address],
[name],
[group],
[device-type],
[measurement_id],
TIME_FROM,
TIME_TO,
[content_id],
[elements_id],
[element-name],
[sensor-type],
[data-type],
DATE_FROM,
[to],
[element_id],
[measurements_id],
[values_id],
[label],
[text])
SELECT *
FROM [VHA].[dbo].[tmp_sensor_info] A
FULL OUTER JOIN #tmp1 B
ON 1 = 1
And here is another message im getting: Msg 206, Level 16, State 2, Line 25
Operand type clash: numeric is incompatible with time
Any ideas?
The solution, which #PanagiotisKanavos alluded to in the comments, is to explicitly list the columns in your final SELECT * FROM.... The order of the columns in that SELECT statement aren't lining up with the columns you're INSERTing into in the destination table.
You may need to run an ad hoc instance of the query to sort out the column order. And then do yourself a favor for future maintenance and be sure to include a table alias on all of the listed columns so you (or whoever has to look at the code next) can easily find out if data is coming from [VHA].[dbo].[tmp_sensor_info] or #tmp1.
This is just one of many dangers in using SELECT * in production code. There's a ton of discussion on the issue in this question: Why is SELECT * considered harmful?
Also, as long as you're in there fixing up the query, consider meaningful table aliases. See: Bad habits to kick : using table aliases like (a, b, c) or (t1, t2, t3).

Return zero for time slot if data is not present

I'm trying to get data for a period of two minutes every minute there should be data for each second for mid,sid,pid combination. if data is not present for a second for each combination it should return IC value as zero.For two minutes there will be 120 time slots if data is not present for mid,sid, pid combination for any time slot it should return zero.This data is used to plot line chart if data is not present it should go down to zero.
CREATE TABLE [dbo].[DeviceData](
[Id] [BIGINT] IDENTITY(1,1) NOT NULL,
[MId] [INT] NOT NULL,
[SId] [INT] NOT NULL,
[PId] [INT] NOT NULL,
[DataTime] [DATETIME] NOT NULL,
[IC] [INT] NOT NULL,
CONSTRAINT [PK_DeviceData] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
SELECT [MId] ,
[SId] ,
[PId] ,
[DataTime] ,
SUM([IC]) AS Value
FROM [DeviceData]
WHERE DataTime BETWEEN DATEADD(MINUTE, -2, GETUTCDATE())
AND GETUTCDATE()
GROUP BY [MId] ,
SID ,
PId ,
[DataTime];
You need a numbers CTE:
with Numbers as
(
select 1 as NN
union all
select NN+1
from Numbers
where NN < 120
)
, Times as
(
select dateadd(ss,
NN,
DATEADD(MINUTE,
-2,
dateadd(ms,
-datepart(ms,
GETUTCDATE()),
GETUTCDATE()) ) as Timeslot
from Numbers
)
select Timeslot, DD.*
from Times
left join DeviceData DD
on Timeslot = dateadd(ms, -datepart(ms, GETUTCDATE()),GETUTCDATE())
OPTION (MAXRECURSION 1000) -- This will bypass the recursion error

Why do i get this error when i do a SELECT..INSERT in SQL Server

Why do i get this error
The select list for the INSERT statement contains more items than the
insert list. The number of SELECT values must match the number of
INSERT columns.
When i run this query
INSERT INTO TempOutputOfGroupifySP
(MonthOfQuery,Associate,[NoOfClaims],[ActualNoOfLines],[AverageTATInDays],
[NoOfErrorsDiscovered],[VarianceinPercent],[NoOfClaimsAudited],[InternalQualInPercent],[ExternalQualInPercent]
)
SELECT (DATENAME(MONTH,[ClaimProcessedDate])) AS MonthOfQuery,
Temp.Associate AS Associate,
COUNT(*) AS [NoOfClaims],
SUM(NoOfLines) AS [ActualNoOfLines] ,
(SUM(DATEDIFF(dd,[ClaimReceivedDate],[ClaimProcessedDate]))/COUNT(*)) AS [AverageTATInDays],
A.[NoOfErrorsDiscovered] AS [NoOfErrorsDiscovered],
Temp.[MonthlyTarget] As [TargetNoOfLines],(Temp.[MonthlyTarget] - COUNT(*)) AS [VarianceInPercent],
B.[NoOfClaimsAudited] AS [NoOfClaimsAudited],
((A.[NoOfErrorsDiscovered]/NULLIF(B.[NoOfClaimsAudited],0))*100) AS [InternalQualInPercent],
NULL AS [ExternalQualInPercent]
FROM
(SELECT COUNT(*) AS [NoOfErrorsDiscovered] FROM TempTableForStatisticsOfAssociates T1 WHERE [TypeOfError] IS NOT NULL) AS A,
(SELECT COUNT(*) AS [NoOfClaimsAudited] FROM TempTableForStatisticsOfAssociates T2 WHERE Auditor IS NOT NULL) AS B,
TempTableForStatisticsOfAssociates Temp
GROUP BY DATENAME(MONTH,([ClaimProcessedDate])),
Temp.Associate,
A.[NoOfErrorsDiscovered],
Temp.[MonthlyTarget],
B.[NoOfClaimsAudited]
Strucuture of the target table is
CREATE TABLE [dbo].[TempOutputOfGroupifySP](
[MonthOfQuery] [nchar](10) NULL,
[Associate] [nvarchar](max) NULL,
[NoOfClaims] [int] NULL,
[ActualNoOfLines] [int] NULL,
[AverageTATInDays] [int] NULL,
[NoOfErrorsDiscovered] [int] NULL,
[VarianceInPercent] [float] NULL,
[NoOfClaimsAudited] [int] NULL,
[InternalQualInPercent] [float] NULL,
[ExternalQualInPercent] [float] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Your INSERT INTO defines 10 colums for the insertion, however, your SELECT statement return 11 columns. You are either missing a column in your INSERT statement or returning one too many in your SELECT statement.
Comparing your table structure and your SELECT and INSERT the following line in your SELECT statement doesn't have a counterpart:
Temp.[MonthlyTarget] As [TargetNoOfLines]

Update a column in table with information from another table

Im already have this:
USE [AdventureWorks2012];
--- somewhere create table
IF OBJECT_ID('[dbo].[PersonPhone]','U') IS NOT NULL
DROP TABLE [dbo].[PersonPhone]
CREATE TABLE [dbo].[PersonPhone](
[BusinessEntityID] [int] NOT NULL,
[PhoneNumber] nvarchar(25) NOT NULL,
[PhoneNumberTypeID] [int] NOT NULL,
[ModifiedDate] [datetime] NOT NULL)
--- and append new column
ALTER Table [dbo].[PersonPhone]
ADD [StartDate] date NULL
--- after this, i want copy dates in this column (at another table, we increase dates by one)
UPDATE [dbo].[PersonPhone]
SET [StartDate] = [NewTable].[NewDate]
FROM (
SELECT DATEADD(day, 1, [HumanResources].[EmployeeDepartmentHistory].[StartDate]) AS [NewDate],
row_number() over(order by (select 1)) AS [RN]
FROM [HumanResources].[EmployeeDepartmentHistory]
) [NewTable]
How to improve query to copy the values ​​from [NewTable] to [dbo].[PersonPhone].[StartDate] row?
At your Update:
UPDATE [dbo].[PersonPhone]
SET [StartDate] = DATEADD(day, 1, [HumanResources].[EmployeeDepartmentHistory].[StartDate])
FROM [HumanResources].[EmployeeDepartmentHistory]
GO
SELECT row_number() over(order by (select 1)) AS [RN] FROM [HumanResources].[EmployeeDepartmentHistory]

How can you define a computed column like this?

I have an Equipment table in SQL Server 2008 like this:
CREATE TABLE [dbo].[Equipment](
[EquipmentID] [nchar](10) NOT NULL,
[EquipmentName] [nchar](50) NOT NULL,
[ProducedDate] [date] NOT NULL,
[WarrantyPeriod] [int] NOT NULL,
[SerialNumber] [nchar](20) NOT NULL,
[BrandID] [tinyint] NOT NULL,
CONSTRAINT [PK_Equipment] PRIMARY KEY CLUSTERED
)
I want to have a computed column WarrantyStatus that will return either Unexpired or Expired when calculating, based on columns ProducedDate and WarrantyPeriod.
This is wrong, but it's what I want:
ALTER TABLE [dbo].[Equipment]
ADD [WarrantyStatus] AS IIF(DATEDIFF(MONTH, [ProducedDate], GETDATE()) < [WarrantyPeriod], "Unexpired", "Expired")
Try:
ALTER TABLE [dbo].[Equipment]
ADD [WarrantyStatus] AS
case when DATEDIFF(MONTH, [ProducedDate], GETDATE()) < [WarrantyPeriod]
then 'Unexpired'
else 'Expired'
end