Query where date = '2016/01/02' not working? - sql-server

SQL FIDDLE DEMO HERE
I have this structure of table:
CREATE TABLE Department
(
[IdDepartment] int,
[Name] varchar(23),
[IdUser] int,
[CreateDate] datetime
);
INSERT INTO Department ([IdDepartment], [Name], [IdUser], [CreateDate])
VALUES
(1, 'Sales', 3, '2016-01-15 17:00:00.000'),
(2, 'Finance', null, '2016-01-13 18:00:00.000' ),
(3, 'Accounting' , 5, '2016-03-21 22:00:00.000'),
(4, 'IT' ,3, '2016-03-21 17:00:00.000'),
(5, 'Secretary',null, '2016-03-21 17:00:00.000'),
(6, 'Sport',3, '2016-02-20 16:00:00.000');
I want to run this query:
select Name
from Department
where CreateDate = '2016-03-21'
This returns 0 rows as a result.
I think it is because the date in the table structure is a datetime but I try to do this and neither works for me:
select Name
from Department
where CreateDate like '%2016-03-21%'
The result should be this:
Name
-----
Accounting
IT
Secretary
How can I get this result?
I hope I explained clearly, thanks

You are comparing a DATETIME value against a pure DATE. You must be aware, that a DATETIME includes a time
2016-03-21 11:00:00 is NOT equal to 2016-03-21
You might compare like this
CAST(YourDate AS DATE)=CAST('2016-03-21' AS DATE)
Hint: As one tiny exception! - CAST(someCol AS DATE) actually is sargable, but it's worth to mention, that it still is not the best idea to do: dba.stackexchange.com/a/34052/70663
or you could try a BETWEEN
YourDate BETWEEN {d'2016-03-21'} AND {ts'2016-03-21 23:59:59'}
or - which is the most prefered in most cases
YourDate >= {d'2016-03-21'} AND YourDate < {d'2016-03-22'}
Avoid manipulations to the column value due to sargability
Better avoid date literals... If you have to, you might read this

Use CAST method to compare date only not time
SELECT * FROM Department
WHERE CAST(CreateDate AS DATE) ='2016-03-21'

Fully agree with #Shnugo
DECLARE #Department TABLE (
IdDepartment INT,
Name VARCHAR(23),
IdUser INT,
CreateDate DATETIME
);
INSERT INTO #Department
VALUES
(1, 'Sales', 3, '2016-01-15 17:00:00'),
(2, 'Finance', NULL, '2016-01-13 18:00:00'),
(3, 'Accounting', 5, '2016-03-21 22:00:00'),
(4, 'IT', 3, '2016-03-21 17:00:00'),
(5, 'Secretary', NULL, '2016-03-21 17:00:00'),
(6, 'Sport', 3, '2016-02-20 16:00:00')
DECLARE #Date DATETIME = '20160321' -- ISO format
SELECT Name
FROM #Department
WHERE CreateDate >= #Date
AND CreateDate < DATEADD(DAY, 1, #Date)

Related

Update all the following values in column depending on previous value

I am looking to do a "cascading" update on a column with all null values except the "first". The order is determined by date ascending.
I have this table
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[StockA]
(
[date] [date] NOT NULL,
[PercentChange] [decimal](19, 6) NULL,
[Price] [decimal](16, 2) NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[StockA] ([date], [PercentChange], [Price])
VALUES (CAST(N'2021-08-19' AS Date), CAST(-0.005100 AS Decimal(19, 6)), NULL)
INSERT INTO [dbo].[StockA] ([date], [PercentChange], [Price])
VALUES (CAST(N'2021-08-20' AS Date), CAST(0.013000 AS Decimal(19, 6)), NULL)
INSERT INTO [dbo].[StockA] ([date], [PercentChange], [Price])
VALUES (CAST(N'2021-08-23' AS Date), CAST(0.015400 AS Decimal(19, 6)), NULL)
INSERT INTO [dbo].[StockA] ([date], [PercentChange], [Price])
VALUES (CAST(N'2021-08-24' AS Date), CAST(0.009500 AS Decimal(19, 6)), NULL)
INSERT INTO [dbo].[StockA] ([date], [PercentChange], [Price])
VALUES (CAST(N'2021-08-18' AS Date), CAST(0.010000 AS Decimal(19, 6)), CAST(100.00 AS Decimal(16, 2)))
GO
SELECT *
FROM StockA
ORDER BY date ASC
The four NULL values should be calculated based on the previous, starting with first NULL value on date 2021-08-19 gives is a calculation of 100(this is the previous value) * (1+PercentChange) = 99.49
I have tried this
WITH CTE AS
(
SELECT
date, PercentChange, Price,
(LAG(Price) OVER (Order by date))*(1+PercentChange) AS NextPrice
FROM
StockA
)
UPDATE CTE
SET Price = NextPrice;
which incorrectly gives me this:
The calculation is correct. The row 2021-08-19 should be 99.49. Nothing wrong there. But something is wrong with my update statement apparently. If I run my CTE query again, the correct value is added to the next row and disappearing from the previous.
Does anybody know how to fill the entire "Price" column, so that there are no NULLS, with calculated values that are based on the "first" (ordered by date ascending) Price?
I am using SQL Server 2019.
One method uses logs to emulate a product aggregation function:
with toupdate as (
select a.*,
exp(sum(log(1 + percent_change)) over (order by date)) / (1 + first_value(percent_change) over (order by date)) as factor,
first_value(price) over (order by date) as orig_price
from stockA
)
update toupdate
set price = orig_price * factor
where price is null;

Union on two tables based on a specific column

I have two tables which have many records , both table have few records where the id is same , I want to have unique group of rows where I have unique id from one particular table incase there are two same id in table
for example
In the above snippet we have empid 1 on both table so , I want all the records such that If there are common empid in both table then value for the common empid the value should be used from Dummy_tab_2 table .
Desired O/P
code to replicate
CREATE TABLE Dummy_tab_1
(
empid int,
Month1 int,
Month2 int,
);
INSERT INTO Dummy_tab_1
VALUES (1, 100, 200), (5,15, 20), (6, 20, 30);
CREATE TABLE Dummy_tab_2
(
empid int,
Month1 int,
Month2 int,
);
INSERT INTO Dummy_tab_2
VALUES (1, 10, 20), (2,15, 20), (3, 20, 30);
I tried this but not sure how to remove the emp id which is not desired
SELECT *
FROM Dummy_tab_2
UNION
SELECT *
FROM Dummy_tab_1
and o/p which I got is this
Using:
SELECT * FROM Dummy_tab_1 WHERE empid NOT IN (SELECT empid FROM Dummy_tab_2)
UNION ALL
SELECT * FROM Dummy_tab_2;
db<>fiddle demo
Using your data examples and what looks like your desired results this should work:
CREATE TABLE Dummy_tab_1
(
empid int,
Month1 int,
Month2 int,
);
INSERT INTO Dummy_tab_1
VALUES (1, 100, 200), (5,15, 20), (6, 20, 30);
CREATE TABLE Dummy_tab_2
(
empid int,
Month1 int,
Month2 int,
);
INSERT INTO Dummy_tab_2
VALUES (1, 10, 20), (2,15, 20), (3, 20, 30);
SELECT COALESCE(DT1.empid, DT2.EmpID) AS EmpID, CASE WHEN DT2.empid IS NOT NULL THEN DT2.Month1 ELSE DT1.Month1 END AS Month1,
CASE WHEN DT2.empid IS NOT NULL THEN DT2.Month2 ELSE DT1.Month2 END AS Month2
FROM Dummy_tab_1 DT1
FULL JOIN Dummy_tab_2 DT2 ON DT1.empid = DT2.empid
ORDER BY COALESCE(DT1.empid, DT2.EmpID)

SQL Server : select data from table based on certain timestamp

I have a table that stores data in a one minute timestamp from each other and I'd like to create a select command, that would fetch data from the :59 minute mark from each hour of a requested period, for example from 01.01.2020 to 01.02.2020.
How could I do this? I attach a sample of data from that table, to which the select command will refer to:
I think you're looking for something like this. In plain language the code says "For the range of start date to end date, select the hourly summary statistics for the test table without skipping any hours."
Table
drop table if exists test_table;
go
create table test_table(
ID int primary key not null,
date_dt datetime,
INP3D decimal(4, 3),
ID_device varchar(20));
Data
insert test_table(ID, date_dt, INP3D, ID_device) values
(1, '2020-08-21 13:44:34.590', 3.631, 'A1'),
(2, '2020-08-21 13:44:34.590', 1.269, 'A1'),
(3, '2020-08-21 13:44:34.590', 0.131, 'A1'),
(4, '2020-08-21 13:44:34.590', 8.169, 'A1');
--select * from test_table;
insert test_table(ID, date_dt, INP3D, ID_device) values
(5, '2020-08-21 11:44:34.590', 3.631, 'A1'),
(6, '2020-08-21 02:44:34.590', 1.269, 'A1'),
(7, '2020-08-22 11:44:34.590', 0.131, 'A1'),
(8, '2020-08-22 01:44:34.590', 8.169, 'A1');
Query
declare
#start_dt datetime='2020-08-21',
#end_dt datetime='2020-08-22';
;with
hours_cte as (
select hours_n
from
(VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),
(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24)) v(hours_n)),
days_cte as (
select dateadd(d, hours_n-1, #start_dt) calc_day from hours_cte where hours_n<=datediff(d, #start_dt, #end_dt)+1)
select
dc.calc_day,
hc.hours_n,
count(*) row_count,
isnull(avg(INP3D), 0) inp3d_avg,
isnull(sum(INP3D+0000.000),0) inp3d_sum
from days_cte dc
cross join hours_cte hc
left join test_table t on t.date_dt between dateadd(hour, (hours_n-1), dc.calc_day)
and dateadd(hour, (hours_n), dc.calc_day)
group by
dc.calc_day,
hc.hours_n
order by
1,2;
This?
SELECT * FROM table WHERE DATEPART(MINUTE, 'your_datetime') = '59'
Datepart

Repeat the column value until value change in same column value

My table structure:
declare #TestTable as table
(
id int,
somedate date,
somevalue int
)
insert into #TestTable values
(1, '2019-01-01', 1000),
(2, '2019-01-02', null ),
(3, '2019-01-03', null),
(4, '2019-01-04', null ),
(5, '2019-01-05', 800),
(6, '2019-01-06', null),
(7, '2019-01-07', null),
(8, '2019-01-08', null),
(9, '2019-01-09', null),
(10, '2019-01-10', 700)
Repeat the column value until any change in value of column (somevalue).. Is it possible with window functions?
Required output:
You can achieve that by using window function as well.
try the following:
select id, somevalue, newvalue=max(somevalue) over (partition by c)
from
(
select id, somevalue
,c=count(somevalue) over (order by id)
from #testtable
) t
order by id;
Please find the demo here.
Try this below logic-
DEMO HERE
SELECT A.*,
(
SELECT somevalue
FROM #TestTable
WHERE id = (
SELECT MAX(id)
FROM #TestTable
WHERE id <= A.id
AND somevalue IS NOT NULL
)
) new_column
FROM #TestTable A
ORDER BY A.id
You can achieve this using COALESCE (Transact-SQL)
.
SELECT
[id]
, somedate
, COALESCE(somevalue,
(SELECT TOP (1) somevalue
FROM #TestTable AS p2
WHERE
p2.somevalue IS NOT NULL
AND p2.[id] <= p.[id] ORDER BY p2.[id] DESC))
FROM #TestTable AS p;
Here is the live db<>fiddle demo.

can we implement innerjoin in the following sql query

These are my tables:
CREATE TABLE forgerock (id INT, [date] DATETIME, empcode INT,[file] VARCHAR);
INSERT INTO forgerock
VALUES
(1, '2015-12-31 01:20:02', 56, 'abc1'),
(2, '2016-01-01 01:20:02', 58, 'abc2'),
(3, '2016-01-02 01:20:02', 46, 'abc3'),
(4, '2016-01-03 01:20:02', 16, 'abc4'),
(5, '2016-01-04 01:20:02', 36, 'abc5');
CREATE TABLE forge (empcode INT, [user_name] VARCHAR);
INSERT INTO forge
VALUES
(56, 'ram'),
(58, 'ram1'),
(46, 'ram2'),
(16, 'ram3'),
(36, 'ram4');
I am trying to print the file name and user_name from the tables with respect to current date and the day before the current date.
I tried the query:
ResultSet resultset = statement.executeQuery("select file from forgerock where '"+date+"' >= CURRENT_DATE('"+date+"', INTERVAL 1 DAY);") ;
but I got the exception:
Incorrect syntax near the keyword 'CURRENT_DATE'.
IF OBJECT_ID('dbo.forgerock', 'U') IS NOT NULL
DROP TABLE dbo.forgerock
CREATE TABLE dbo.forgerock (id INT PRIMARY KEY, [date] DATETIME, empcode INT,[file] VARCHAR(10));
INSERT INTO dbo.forgerock
VALUES
(1, '2015-12-31 01:20:02', 56, 'abc1'),
(2, '2016-01-01 01:20:02', 58, 'abc2'),
(3, '2016-01-02 01:20:02', 46, 'abc3'),
(4, '2016-01-03 01:20:02', 16, 'abc4'),
(5, '2016-01-04 01:20:02', 36, 'abc5');
IF OBJECT_ID('dbo.forge', 'U') IS NOT NULL
DROP TABLE dbo.forge
CREATE TABLE dbo.forge (empcode INT PRIMARY KEY, [user_name] VARCHAR(10));
INSERT INTO dbo.forge
VALUES (56, 'ram'),(58, 'ram1'),(46, 'ram2'),(16, 'ram3'),(36, 'ram4')
DECLARE #dt DATETIME = FLOOR(CAST(GETDATE() AS FLOAT))
SELECT *
FROM dbo.forge
WHERE empcode IN (
SELECT f.empcode
FROM dbo.forgerock f
WHERE f.[date] BETWEEN DATEADD(DAY, -1, #dt) AND #dt
)
output -
empcode user_name
----------- ----------
16 ram3
SELECT fr.file, f.user_name
FROM forgerock fr inner join forge f on fr.empcode = f.empcode
WHERE fr.date >= DATE_ADD(NOW(), INTERVAL -1 DAY)
You can use datediff to get the difference between two dates.
Try this :
ResultSet resultset = statement.executeQuery("select file from forgerock where DATEDIFF(day, GETDATE(), '" + date + "') >= 1") ;
To test the query use this one :
SELECT * FROM forgerock WHERE DATEDIFF(day, GETDATE(), #date) >= 1;
Just replace the #date with the value you want, for example '2016-01-02'
Use this filter:
SELECT [file]
FROM forgerock
WHERE [date] >= DATEADD(DAY, DATEDIFF(DAY,0,GETDATE()-1),0)
The DATEADD expression above will always return 12:00am yesterday morning, allowing your query to only return records from yesterday or today.
Bonus Tip: avoid using reserved keywords (such as file and date) as column or table names.
Since am using ms sql the code should be the following way
SELECT fr.file, f.user_name FROM forgerock fr inner join forge f on fr.empcode = f.empcodewhere [date] >= DATEADD(DAY, DATEDIFF(DAY,0,GETDATE()-1),0)
which will result in printing the two tables file from forgerock and user_name from forge
You have to try following query:-
SELECT fr.file, f.user_name
FROM forgerock fr inner join forge f on fr.empcode = f.empcode
AND `date' >= (DATE_ADD(`date`, INTERVAL 1 day))

Resources