Sum of Columns which Contain Differennt Data Type - sql

I am trying to sum the cost value but the problem I believe is in my cost column there are not set and null values beside actual values. So Sum(t.cost) gives me wrong sum and coalesce(t.cost) gives me the wrong sum. What needs to be done to get the right sum for each student?

I presume that your "cost" column is not numeric ?!? Whatever...
declare #t table (id int, cost varchar(10) null)
insert into #t values (1,'123.456')
insert into #t values (2,'456.789')
insert into #t values (3,null)
insert into #t values (3,'notset')
select sum(cast(nullif(cost,'notset') as money)) from #t

Related

Find max value from coalesce function

This is my query:
declare #t table (date1 date,date2 date,date3 date)
insert into #t values ('2019-01-01','2019-01-20','2019-02-10')
insert into #t values (null,null,'2019-02-01')
insert into #t values (null,'2019-02-01','2019-02-02')
My expected output is:
2019-02-10
2019-02-01
2019-02-02
I tried to use coalesce like :
select coalesce(date1,date2,date3) as maxdate from #t
I know coalesce returns first not null value. So what I can do to get my desired result.
This will do the trick.
Basically you transform every row in a data-set, using VALUES clause, and then just get the MAX value.
SELECT (
SELECT MAX(LastUpdateDate)
FROM (VALUES (date1),(date2),(date3)) AS UpdateDate(LastUpdateDate)) AS LastUpdateDate
FROM #t
coalesce() has nothing to do with this. Unfortunately, SQL Server does not support greatest(). But you can use apply:
select t.*, m.max_date
from #t t cross apply
(select max(dte) as max_date
from (values (t.date1), (t.date2), (t.date3)) v(dte)
) m;
The max() ignores NULL values, so this does what you expect.
Here is a db<>fiddle.
Personally I would normalise your data, by unpivoting it, and then getting the MAX in the group. This does, however, require you have some kind of column to identify the row (I use an IDENTITY in this example):
DECLARE #t table (id int IDENTITY,
date1 date,
date2 date,
date3 date);
INSERT INTO #t
VALUES ('2019-01-01', '2019-01-20', '2019-02-10');
INSERT INTO #t
VALUES (NULL, NULL, '2019-02-01');
INSERT INTO #t
VALUES (NULL, '2019-02-01', '2019-02-02');
SELECT MAX([date])
FROM #t t
CROSS APPLY (VALUES(t.date1),(date2),(t.date3))V([date])
GROUP BY t.id;

SQL Server: return joined data from insert select

I perform steps:
Create temporal table and fill it with data and unique order column [_oid]
Insert everything from temporal table into real table except fictional [_oid], outputting generated [id]'s
Return those generated [id]'s along with corresponding [_oid]
SQL:
CREATE TABLE #temp
(
[Hash] INT NOT NULL,
[Size] INT NOT NULL,
[Data] NVARCHAR(MAX),
[_oid] INT NOT NULL
)
--here insert data into #temp--
INSERT [dbo].[TestObjects]
OUTPUT INSERTED.[Id]
SELECT [Hash], [Size], [Data]
FROM #temp
DROP TABLE #temp
How I can return ([Id], [_oid]) rows ? ....Or at least return [Id] ordered by [_oid] ?
I know insert does not preserve order of inserted items in it's output, but still...
I think you what you are asking for is INSERT INTO, as so:
INSERT INTO [dbo].[TestObjects]
SELECT Hash, Size, Data FROM #temp
ORDER BY _oid
But as you say, there's no guarantee about order when you select from TestObjects, so if it's important can you not have a field in TestObjects you can ORDER BY when you SELECT from it?
IF your insert into #temp is such that both o_id and (hash,size,data) are unique for each row (ie keys), then you could retrieve the inserted o_id from #temp:
select t.[_oid],to.[Id]
from #temp t
inner join [dbo].[TestObjects] to
on t.Hash=to.Hash and t.Size=to.Size and t.data=to.data
As noted by George Menoutis, I did merge:
MERGE [dbo].[TestObjects] AS T_Base
USING #temp AS T_Source
ON (0<>0)
WHEN NOT MATCHED THEN INSERT ([Hash],[Size],[Data]) VALUES (T_Source.[Hash],T_Source.[Size],T_Source.[Data])
OUTPUT INSERTED.[Id], T_Source.[_oid];
If anyone have better approach - feel free to contribute to this answer.

SQL Server - Partition by or Row num or Subquery - Assistance

I have the below problem.
I am trying to see how often a customer has requested Re-Activation of their Internet account.
The problem is, we capture a limited set of data to group on.
So my data set is below.
I am trying to Count from the first time a Re-Activation request was created until the First time it was COMPLETED, once it has been completed finish the count of days it took for the request to complete and count the number of NON COMPLETIONS and SENT statuses which occurred between that time.
Below is an image of the sample data as well as the sql for the table.
Hope somebody can provide a little help.
(using SQL server 2005 compatibility)
http://imgur.com/a/9yCJm
enter image description here
CREATE TABLE #temp
(
Identifier varchar(20)NOT NULL
,CreatedDate DATETIME NOT NULL
,CompletedDate DATETIME NOT NULL
,SN_Type varchar(20) NOT NULL
,SN_Status varchar(20) NOT NULL
)
;
INSERT INTO #temp
VALUES('64074558792','20160729','20160805','Re-Activattion','SENT');
INSERT INTO #temp
VALUES('64074558792','20160810','20160810','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES('64074558792','20160812','20160812','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES('64074558792','20160811','20160811','Re-Activattion','COMP');
INSERT INTO #temp
VALUES('64074558792','20160811','20160813','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES ('61030203647','20160427','20160427','Re-Activattion', 'COMP');
INSERT INTO #temp
VALUES('61030203647','20160427','20160427','Re-Activattion', 'N-CO');
INSERT INTO #temp
VALUES('61030203647','20160422','20160422','Re-Activattion', 'N-CO');
INSERT INTO #temp
VALUES('61030203647','20170210','20170210','Re-Activattion', 'COMP');
INSERT INTO #temp
VALUES('61030203688','20170409','20170210','Re-Activattion', 'SENT');
INSERT INTO #temp
VALUES('61030203699','20170409','20170210','De-Activattion', 'COMP');

Insert error in sql cursor

I have this SQL Server query with a cursor:
DECLARE #ids TABLE(id varchar(50))
INSERT INTO #ids VALUES ('1098264', '1098859', '1098860', '1098267', '1098265')
But when I run the code, I get an error:
Insert Error: Column name or number of supplied values does not match table definition.
You have only one column in table i.e id and you are trying to insert 5 column values in table.
Try this
Create table :
DECLARE #ids TABLE(id varchar(50))
Insert values to table :
INSERT INTO #ids VALUES ('1098264')
INSERT INTO #ids VALUES ('1098859')
INSERT INTO #ids VALUES ('1098860')
INSERT INTO #ids VALUES ('1098267')
INSERT INTO #ids VALUES ('1098265')
You need to use a pair of bracket for each row like below:
INSERT INTO #ids VALUES ('1098264'),('1098859'),('1098860'),('1098267'),('1098265')
There are three ways of inserting multiple rows into a table (other than via a select statement)
INSERT INTO FOO (columna,columnb)
VALUES (1,a)
INSERT INTO FOO (columna,columnb)
VALUES (2,b)
INSERT INTO FOO (columna,columnb)
VALUES (3,c)
The second
INSERT INTO FOO (columna,columnb)
select 1,'a'
UNION ALL
select 2,'b'
UNION ALL
select 3,'c'
Thirdly (only works SQLServer 2008 and up)
INSERT INTO FOO (columna,columnb)
VALUES (1,'a'),(2,'b'),(3,'c')
In the example in your question, you were trying to insert multiple fields into one column, which is why you got the error.
You have only 1 column in the table but are trying to insert 5 values.
First declare 5 different columns in the table to hold 5 values
For Example:-
declare #IDS_1 varchar(50)
,#IDS_2 varchar(50)
,#IDS_3 varchar(50)
,#IDS_4 varchar(50)
,#IDS_5 varchar(50)
INSERT INTO #IDS VALUES ('1098264'
,'1098859'
,'1098860'
,'1098267'
,'1098265')

INSERT multiple rows and OUTPUT original (source) values

I would like to INSERT multpile rows (using INSERT SELECT), and OUTPUT all the new and old IDs into a "mapping" table.
How can I get the original ID (or any source values) in the OUTPUT clause? I don't see a way to get any source values there.
Here is a minimal code example:
-- create some test data
declare #t table (id int identity, name nvarchar(max))
insert #t ([name]) values ('item 1')
insert #t ([name]) values ('another item')
-- duplicate items, storing a mapping from src ID => dest ID
declare #mapping table (srcid int, [newid] int)
insert #t ([name])
output ?????, inserted.id into #mapping-- I want to use source.ID but it's unavailable here.
select [name] from #t as source
-- show results
select * from #t
select * from #mapping
My actual scenario is more complex, so for example I cannot create a temp column on the data table in order to store a "original ID" temporarily, and I cannot uniquely identify items by anything other than the 'ID' column.
Interesting question. For your example, a possible cheat is to depend on the fact that you are doubling the number of rows. Assuming that rows are never deleted and the [id] column remains dense:
-- create some test data
declare #t table (id int identity, name nvarchar(max))
insert #t ([name]) values ('item 1')
insert #t ([name]) values ('another item')
-- duplicate items, storing a mapping from src ID => dest ID
declare #mapping table (srcid int, [newid] int)
declare #Rows as Int = ( select Count(42) from #t )
insert #t ([name])
output inserted.id - #Rows, inserted.id into #mapping
select [name] from #t as source order by source.id -- Note 'order by' clause.
-- show results
select * from #t
select * from #mapping