SQL SERVER - Using DATEDIFF with subquery column - sql

I have a query that looks like:
SELECT
col1
,...
,col3
,(SELECT col3 FROM table where <clause>) AS MinPickTime
,(SELECT col3 FROM table where <clause>) AS MaxPickTime
,DATEDIFF(d, MinPickTime, MaxPickTime)
FROM table
However the DATEDIFF line does not like the alias columns.
In short, how do I give DATEDIFF an alias column derived by a subquery?

Use derived tables concept to access alias name.
SELECT col1
,...
,col3,
MinPickTime,
MaxPickTime ,
DATEDIFF(d, MinPickTime, MaxPickTime)
FROM (
SELECT
col1
,...
,col3
,(SELECT col3 FROM table where <clause>) AS MinPickTime
,(SELECT col3 FROM table where <clause>) AS MaxPickTime
FROM table
)z

with temp as (SELECT
col1
,...
,col3
,(SELECT col3 FROM table where <clause>) AS MinPickTime
,(SELECT col3 FROM table where <clause>) AS MaxPickTime
FROM table)
select DATEDIFF(d,MaxPickTime,MinPickTime) from temp

Related

How to write a SQL query for the below?

I have two tables with n of columns from Col1 to Col30
Table 1.
Templateid Col1 Col2 Col3 Col4 ...
95 2019-05-28 1234 test123 123456
Table 2.
Templateid DisplayName ColumnName
95 date col1
95 rank col2
95 purpose col3
95 sign col4
Expected Results.
Col1Name Col1Value Col2Name Col2Value Col3Name Col3Value ....
date 2019-05-28 rank 1234 purpose test123
This is a crude way of doing it and if you do not know the number of columns in each table you would need to use dynamic sql to enumerate them out but for the purposes of this example I have assumed you do know the number of columns and the names you want to populate.
The union query allows you to pre-populate the desired column names using the col1 syntax, then the pivot allows you to match up the displaynames and the display values. A case statement is required to ensure the correct values are shown and you do need to populate your derived column names for the pivot query but you do get the desired outcome this way.
declare #table1 table (
Templateid int,
Col1 date,
col2 int,
col3 nvarchar(10),
col4 int
);
insert into #table1 (Templateid, col1, col2, col3, col4)
values
(95, '2019-05-28', '1234', 'test123', '123456');
declare #table2 table (
Templateid int,
Displayname nvarchar(10),
ColumnName nvarchar(10)
);
insert into #table2 (Templateid, Displayname, ColumnName)
values
(95, 'date', 'col1'),
(95, 'rank', 'col2'),
(95, 'purpose', 'col3'),
(95, 'sign', 'col4');
select * from
(
select columnname+'Name' as columnname, Displayname
from #table2 t2
union
select columnname+'Value', case when columnname='col1' then cast(col1 as nvarchar(15))
when columnname='col2' then cast(col2 as nvarchar(15))
when columnname='col3' then cast(col3 as nvarchar(15))
when columnname='col4' then cast(col4 as nvarchar(15)) end
from #table1 t1 inner join #table2 t2 on t1.Templateid=t2.Templateid) src
pivot
(max(displayname) for columnname in ([col1Name],[col1Value], [col2Name],[col2Value], [col3Name],[col3Value], [col4Name],[col4Value])) piv;

Showing the result of COALESCE into separate columns based from where they where retrieved

I have a table with many NULL values. Therefore I use the COALESCE function to retrieve the NON NULL values. This works fine when the result of the COALESCE is to be placed in a single Column. However I need to place the values of the COALESCE into separate Columns depending from where they where picked.
E.g. I have the following table.
SELECT COALESCE(Col1, Col2, Col3, Col4) FROM Table 1
Will produce:-
Column1
1
1
3
4
However I do not want that result but I want this result:-
Col1 Col2 Col3 Col4
1 - - -
- 1 - -
- - 3 -
- 4 - -
As you can see I want only one field populated (that why I'm suing COALESCE but the result of COALESCE should be placed as illustrated, NOTICE ONE VALUE PER ROW.
Any ideas of how I can achieve this result please.
coalesce can be built with case statements. You need something like the below:
select col1
, case when col1 is not null then null else col2 end 'Col2'
, case when col1 is not null or col2 is not null then null else col3 end 'Col3'
, case when col1 is not null or col2 is not null or col3 is not null then null else col4 end 'Col4'
from table
You can achieve this with a combination of PIVOT, UNPIVOT and ROW_NUMBER.
declare #t table(rn int identity(1,1) primary key, col1 int, col2 int, col3 int, col4 int);
insert #t values (1,null,null,null), (null,1,0,null), (null,null,3,null), (null,4,null,2);
with a as (
select *, ranking = row_number() over (partition by rn order by col)
from #t a
unpivot ([val] for [col] in ([col1],[col2],[col3],[col4])) p
)
select *
from a
pivot (min(val) for [col] in ([col1],[col2],[col3],[col4])) p
where ranking = 1

Change row value to column in SQL

I have table in sql i want to change fieldColumnName as a column and fieldValue as a row.
this is my table image
As per your question, You want to alter table (change column name as well as data type)
ALTER TABLE tablename
CHANGE `fieldColumnName` `column` VARCHAR(255),
CHANGE `fieldValue` `row` VARCHAR(255)
In above query you change datatype as you wish.
If you know all the possible values in the fieldColumnName column then you could use pivot like this:
declare #data table(fieldValue varchar(50), fieldColumnName varchar(50))
INSERT INTO #data
SELECT '1 - value', 'col1'
UNION
SELECT '2 - value', 'col2'
UNION
SELECT NULL, 'col6'
select *
from #data
select col1, col2, col3
from
(
select fieldValue, fieldColumnName
from #data
) d
pivot
(
max(fieldValue)
for fieldColumnName in (col1, col2, col3)
) piv;

Convert each column of a record into separate record

I have a record:
DECLARE #Tbl AS TABLE(Col1 VARCHAR(10), Col2 VARCHAR(10), Col3 VARCHAR(10));
INSERT INTO #Tbl
VALUES('Val1', 'Val2', 'Val3')
-- Source Record
SELECT Col1, Col2, Col3 FROM #Tbl
Result: Val1 Val2 Val3
I want result of each column as separate two column records like first column will become the title of source column and second column should be the value of source column like the result of below query in which I have achieved the result by UNION ALL :
--Query for Target Result
SELECT 'Col1' AttributeTitle, CONVERT(VARCHAR, Col1) AttributeValue FROM #Tbl
UNION ALL SELECT 'Col2' AttributeTitle, CONVERT(VARCHAR, Col2) AttributeValue FROM #Tbl
UNION ALL SELECT 'Col3' AttributeTitle, CONVERT(VARCHAR, Col3) AttributeValue FROM #Tbl
Problem in this query is I have to explicitly define the columns, is there any way that it should dynamically get the columns names and their values?
You could use UNPIVOT but you still need to know the names of the columns.
SELECT ColumnName, ValueName
FROM (SELECT * FROM #Tbl) AS Data
UNPIVOT
( ValueName
FOR ColumnName IN (Col1, Col2, Col3)
) AS PivottedOutput
I like the apply method for unpivoting in SQL Server:
select v.*
from #tbl t cross apply
(values ('col1', col1),
('col2', col2),
('col3', col3)
) v(AttributeTitle, AttributeValue);
This simplifies the query but it does not directly answer the question.
If you want a variable number of columns, then you are going to have to use dynamic SQL. This is a bit cumbersome on a real table. However, with a table variable or a temporary table, you have the additional issue of scoping rules -- the name of the table will not be in scope when you execute the statement.

SQL Server: Select from two tables and insert into one

I have a stored procedure with two table variables (#temp and #temp2).
How can I select the values from both temp tables (Both table variables contain one row) and insert them all in one table ?
I tried the following but this didn't work and I got the error that the number of SELECT and INSERT statements does not match.
DECLARE #temp AS TABLE
(
colA datetime,
colB nvarchar(1000),
colC varchar(50)
)
DECLARE #temp2 AS TABLE
(
colD int
)
...
INSERT INTO MyTable
(
col1,
col2,
col3,
col4
)
SELECT colD FROM #temp2,
colA FROM #temp,
colB FROM #temp,
colC FROM #temp
Many thanks for any help with this, Tim.
As both table variables have a single row you can cross join them.
INSERT INTO MyTable
(col1,
col2,
col3,
col4)
SELECT t.colA,
t.colB,
t.colC,
t2.colD
FROM #temp t
CROSS JOIN #temp2 t2
you should use this if you have only single row in both table #temp and #temp2, because this is a cartesian product.
INSERT INTO MyTable(col1,col2,col3,col4)
SELECT t.colA,
t.colB,
t.colC,
t2.colD
FROM #temp t,#temp2 t2