How to copy data of datetime column to another column in SQL - sql

How can I copy data of all column from datetime column to another column without hour minute and second.
Table A
ID Time Time2
1 2012-08-08 00:38:59.783 NULL
After copy
ID Time Time2
1 2012-08-08 00:38:59.783 2012-08-08

update table
set time2=cast (time as date)
DEMO

create table #temp (Time datetime, Time2 date)
insert into #temp values ('2012-08-08 00:38:59.783', null)
insert into #temp values ('2012-08-05 02:30:34.123', null)
update #temp set Time2 = Time
select * from #temp
drop table #temp

Related

Optimize this query without using not exist repeatably, is there a better way to write this query?

For example I have three table where say DataTable1, DataTable2 and DataTable3
and need to filter it from DataRange table, every time I have used NOT exist as shown below,
Is there a better way to write this.
Temp table to hold some daterange which is used for fiter:
Declare #DateRangeTable as Table(
StartDate datetime,
EndDate datetime
)
Some temp table which will hold data on which we need to apply date range filter
INSERT INTO #DateRangeTable values
('07/01/2020','07/04/2020'),
('07/06/2020','07/08/2020');
/*Table 1 which will hold some data*/
Declare #DataTable1 as Table(
Id numeric,
Date datetime
)
INSERT INTO #DataTable1 values
(1,'07/09/2020'),
(2,'07/06/2020');
Declare #DataTable2 as Table(
Id numeric,
Date datetime
)
INSERT INTO #DataTable2 values
(1,'07/10/2020'),
(2,'07/06/2020');
Declare #DataTable3 as Table(
Id numeric,
Date datetime
)
INSERT INTO #DataTable3 values
(1,'07/11/2020'),
(2,'07/06/2020');
Now I want to filter data based on DateRange table, here I need some optimized way so that i don't have to use not exists mutiple times, In real senario, I have mutiple tables where I have to filter based on the daterange table.
Select * from #DataTable1
where NOT EXISTS(
Select 1 from #DateRangeTable
where [Date] between StartDate and EndDate
)
Select * from #DataTable2
where NOT EXISTS(
Select 1 from #DateRangeTable
where [Date] between StartDate and EndDate
)
Select * from #DataTable3
where NOT EXISTS(
Select 1 from #DateRangeTable
where [Date] between StartDate and EndDate
)
Instead of using NOT EXISTS you could join the date range table:
SELECT dt.*
FROM #DataTable1 dt
LEFT JOIN #DateRangeTable dr ON dt.[Date] BETWEEN dr.StartDate and dr.EndDate
WHERE dr.StartDate IS NULL
It may perform better on large tables but you would have to compare the execution plans and make sure you have indexes on the date columns.
I would write the same query... but if you can change table structure I would try to improve performance adding two columns to specify the month as an integer (I suppose is the first couple of figures).
Obviously you have to test with your data and compare the timings.
Declare #DateRangeTable as Table(
StartDate datetime,
EndDate datetime,
StartMonth tinyint,
EndMonth tinyint
)
INSERT INTO #DateRangeTable values
('07/01/2020','07/04/2020', 7, 7),
('07/06/2020','07/08/2020', 7, 7),
('07/25/2020','08/02/2020', 7, 8); // (another record with different months)
Now your queries can use the new column to try to reduce comparisons (is a tinyint, sql server can partition records if you define a secondary index for StartMonth and EndMonth):
Select * from #DataTable1
where NOT EXISTS(
Select 1 from #DateRangeTable
where (DATEPART('month', [Date]) between StartMonth and EndMonth)
and ([Date] between StartDate and EndDate)
)

Create automatically generated timestamp column in table?

How to create a automatically generated timestamp column in table in Microsoft SQL Server 2019? Timestamp column should be automatically generated when I insert or update table.
In IBM Db2 database the syntax is the following:
create table myschema.mytable (col1 int, col2 timestamp not null generated always for each row on update as row change timestamp
insert into myschema.mytable (col1) values (1)
update myschema.mytable set col1 = 2
After insert/update of column col1, column col2 is automatically generated as current timestamp.
In Microsoft SQL Server you can try this code:
CREATE TABLE myschema.mytable
(
col1 int,
col2 datetime not null default(current_timestamp)
)
INSERT INTO myschema.mytable(col1) VALUES (1)
UPDATE myschema.mytable SET col1 = 2
SELECT * FROM myschema.mytable
Update:
Let's create temporary table for test
DECLARE #mytable TABLE
(
col1 int,
col2 datetime not null default(current_timestamp)
)
INSERT INTO #mytable(col1) VALUES (1)
SELECT * FROM #mytable
UPDATE #mytable SET col1 = 2
SELECT * FROM #mytable

Search By Time (only) in DateTime SQL column

I am working with SQL Server & PHP and using stored procedures.
I have a table called myTable. I has a column start_time (DateTime Format).
start_time
-----------------------
2019-05-23 12:20:22.000
2019-08-02 01:21:02.000
2019-02-10 22:32:17.000
2019-08-14 04:56:24.000
I want to filter results by time only.
For-example: BETWEEN 22:20:10.000 AND 04:56:24.000
But, It's not Working.
Simple casting to time datatype will work:
select * from myTable
where cast(start_time as time) >= '22:00:00.000'
or cast(start_time as time) <= '04:00:00.000'
Note that applying a CAST function to the start_time column in the WHERE clause predicate will prevent an index that column from being used efficiently. A full table scan will be required unless other criteria are specified.
this code will work please check
create table #temp
(
[Date] datetime
)
insert into #temp values ('2019-05-23 12:20:22.000')
insert into #temp values ('2019-08-02 01:21:02.000')
insert into #temp values ('2019-02-10 22:32:17.000')
insert into #temp values ('2019-08-14 04:56:24.000')
select cast([Date] as date) as [Date],convert(char(15), [Date], 108) [Time]
from #temp
where convert(char(15), [Date], 108) between '04:56:24' and '22:32:17'
Drop table #temp

how to add days to a date column from an Integer column, by SQL

I have Column 'A' which is a date column CREATED AS CAST(GETDATE() AS DATE) and column 'B' which is an integer column.
I want to create column C to show A+B as a date.
Try it like this
CREATE TABLE #test(DateColumn DATETIME, IntColumn INT);
INSERT INTO #test VALUES
({ts'2016-01-01 00:00:00'},1)
,({ts'2016-01-10 11:30:00'},-2)
,(GETDATE(),3);
SELECT DateColumn AS A
,IntColumn AS B
,DATEADD(DAY,IntColumn,DateColumn) AS C
FROM #test;
DROP TABLE #test;
Btw: Adding full DAYs would even work with simple DateValue+IntValue

Pseudo Random Repeatable Sort in SQL Server (not NEWID() and not RAND())

I would like to randomly sort a result in a repeatable fashion for purposes such as paging. For this NEWID() is too random in that the same results cannot be re-obtained. Order by Rand(seed) would be ideal as with the same seed the same random collection would result. Unfortunately, the Rand() state resets with every row, does anyone have a solution?
declare #seed as int;
set #seed = 1000;
create table temp (
id int,
date datetime)
insert into temp (id, date) values (1,'20090119')
insert into temp (id, date) values (2,'20090118')
insert into temp (id, date) values (3,'20090117')
insert into temp (id, date) values (4,'20090116')
insert into temp (id, date) values (5,'20090115')
insert into temp (id, date) values (6,'20090114')
-- re-seeds for every item
select *, RAND(), RAND(id+#seed) as r from temp order by r
--1 2009-01-19 00:00:00.000 0.277720118060575 0.732224964471124
--2 2009-01-18 00:00:00.000 0.277720118060575 0.732243597442382
--3 2009-01-17 00:00:00.000 0.277720118060575 0.73226223041364
--4 2009-01-16 00:00:00.000 0.277720118060575 0.732280863384898
--5 2009-01-15 00:00:00.000 0.277720118060575 0.732299496356156
--6 2009-01-14 00:00:00.000 0.277720118060575 0.732318129327415
-- Note how the last column is +=~0.00002
drop table temp
-- interestingly this works:
select RAND(#seed), RAND()
--0.732206331499865 0.306382810665955
Note, I tried Rand(ID) but that just turns out to be sorted. Apparently Rand(n) < Rand(n+1)
Building off of gkrogers hash suggestion this works great. Any thoughts on performance?
declare #seed as int;
set #seed = 10;
create table temp (
id int,
date datetime)
insert into temp (id, date) values (1,'20090119')
insert into temp (id, date) values (2,'20090118')
insert into temp (id, date) values (3,'20090117')
insert into temp (id, date) values (4,'20090116')
insert into temp (id, date) values (5,'20090115')
insert into temp (id, date) values (6,'20090114')
-- re-seeds for every item
select *, HASHBYTES('md5',cast(id+#seed as varchar)) r
from temp order by r
--1 2009-01-19 00:00:00.000 0x6512BD43D9CAA6E02C990B0A82652DCA
--5 2009-01-15 00:00:00.000 0x9BF31C7FF062936A96D3C8BD1F8F2FF3
--4 2009-01-16 00:00:00.000 0xAAB3238922BCC25A6F606EB525FFDC56
--2 2009-01-18 00:00:00.000 0xC20AD4D76FE97759AA27A0C99BFF6710
--3 2009-01-17 00:00:00.000 0xC51CE410C124A10E0DB5E4B97FC2AF39
--6 2009-01-14 00:00:00.000 0xC74D97B01EAE257E44AA9D5BADE97BAF
drop table temp
EDIT: Note, the declaration of #seed as it's use in the query could be replace with a parameter or with a constant int if dynamic SQL is used. (declaration of #int in a TSQL fashion is not necessary)
You can use a value from each row to re-evaluate the rand function:
Select *, Rand(#seed + id) as r from temp order by r
adding the ID ensures that the rand is reseeded for each row. But for a value of seed you will always get back the same sequence of rows (provided that the table does not change)
Creating a hash can be much more time consuming than creating a seeded random number.
To get more variation in the ourput of RAND([seed]) you need to make the [seed] vary significantly too. Possibly such as...
SELECT
*,
RAND(id * 9999) AS [r]
FROM
temp
ORDER BY
r
Using a constant ensures the replicability you asked for. But be careful of the result of (id * 9999) causing an overflow if you expect your table to get big enough...
SELECT *, checksum(id) AS r FROM table ORDER BY r
This kind of works. Although the output from checksum() does not look all that random to me. The MSDN Documentation states:
[...], we do not recommend using CHECKSUM to detect whether values have changed, unless your application can tolerate occasionally missing a change. Consider using HashBytes instead. When an MD5 hash algorithm is specified, the probability of HashBytes returning the same result for two different inputs is much lower than that of CHECKSUM.
But may be it faster.
After doing some reading this is an accepted method.
Select Rand(#seed) -- now rand is seeded
Select *, 0 * id + Rand() as r from temp order by r
Having id in the expression causes it to be reevaluated every row. But multiplying it by 0 ensures that it doesnt not affect the outcome of rand.
What a horrible way of doing things!
create table temp (
id int,
date datetime)
insert into temp (id, date) values (1,'20090119')
insert into temp (id, date) values (2,'20090118')
insert into temp (id, date) values (3,'20090117')
insert into temp (id, date) values (4,'20090116')
insert into temp (id, date) values (5,'20090115')
insert into temp (id, date) values (6,'20090114')
-- re-seeds for every item
select *, NEWID() r
from temp order by r
drop table temp
This has worked well for me in the past, and it can be applied to any table (just bolt on the ORDER BY clause):
SELECT *
FROM MY_TABLE
ORDER BY
(SELECT ABS(CAST(NEWID() AS BINARY(6)) % 1000) + 1);