can we implement innerjoin in the following sql query - sql-server

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))

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;

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

How to INSERT data into multiple columns from multiple queries?

This SQL Server stored procedure takes four parameters to show a table order by dates between FromDate and ToDate as follows:
CREATE PROCEDURE GetLedger
(#FromDate date,
#ToDate date,
#Supplier int,
#MOP int)
AS
BEGIN
DECLARE #ExpTABLE TABLE
(
RowNo int,
TranDate date,
NetExpense float
)
INSERT INTO #ExpTABLE
SELECT
ROW_NUMBER() OVER (ORDER BY TranDate), TranDate, SUM(NetAmount)
FROM
Expenditure
WHERE
TranDate BETWEEN #FromDate AND #ToDate
AND SupplierID = #Supplier
AND MOP = #MOP
GROUP BY
TranDate
DECLARE #Data TABLE
(
RDate DATE,
Expense float
PRIMARY KEY (RDate)
)
WHILE (#FromDate <= #ToDate)
BEGIN
INSERT INTO #Data (RDate)
VALUES (#FromDate)
SELECT #FromDate = DATEADD(DAY, 1, #FromDate)
END
WHILE (#FromDate <= #ToDate)
BEGIN
INSERT INTO #Data (Expense)
SELECT NetExpense
FROM #ExpTABLE
WHERE TranDate = #FromDate
SELECT #FromDate = DATEADD(DAY, 1, #FromDate)
END
SELECT * FROM #Data
END
--EXEC GetLedger '2020-03-01' ,'2020-03-31',2,2
The data in #ExpTABLE is like this:
RowNo TranDate NetExpense
------------------------------
1 2020-03-15 35
Now, I am trying to INSERT this NetExpense of '2020-03-15' in #Data Table in the respective date while the rest NetExpense of Other dates remain null.
This INSERT query:
WHILE (#FromDate <= #ToDate)
BEGIN
INSERT INTO #Data (Expense)
SELECT NetExpense
FROM #ExpTABLE
WHERE TranDate = #FromDate
SELECT #FromDate = DATEADD(DAY, 1, #FromDate)
END
is inserting NULL in all dates including '2020-03-15'. What am I missing here?
In order to have a row for every date in your range it would be helpful to use a Calendar table. There are lots of resources available on how to do that like this one. Another option is to create your a calendar table on the fly as a common table expression (CTE) like this.
When developing a stored procedure I like to get it working just as a regular SQL statement and once I have that I can transform it into a stored procedure. So here is the regular SQL statement that should get you going.
DECLARE
#FromDate DATE
, #ToDate DATE
, #Supplier INT
, #MOP INT;
-- set these values to whatever you would pass to your stored procedure
SET #FromDate = '2020-03-01';
SET #ToDate = '2020-03-31';
SET #Supplier = 2;
SET #MOP = 3;
DECLARE #Expenditure TABLE
(
ID INT NOT NULL
, TranDate DATE NOT NULL
, SupplierID INT NOT NULL
, MOP INT NOT NULL
, NetAmount DECIMAL(10, 2) NOT NULL
);
INSERT INTO #Expenditure (ID, TranDate, SupplierID, MOP, NetAmount)
VALUES
(1, '02/28/2020', 2, 3, 200.12)
, (2, '03/15/2020', 2, 3, 125.10)
, (3, '03/15/2020', 2, 3, 74.90)
, (4, '03/17/2020', 3, 3, 150.32)
, (5, '03/18/2020', 2, 3, 250.78)
;WITH cteCalendar (MyDate) AS
(
SELECT CONVERT(DATE, #FromDate) AS MyDate
UNION ALL
SELECT DATEADD(DAY, 1, MyDate)
FROM cteCalendar
WHERE DATEADD(DAY, 1, MyDate) <= #ToDate
)
SELECT
ROW_NUMBER() OVER (ORDER BY x.TranDate) AS [RowNo]
, x.TranDate
, x.NetExpense
FROM (
SELECT
c.MyDate AS TranDate
, SUM(e.NetAmount) AS [NetExpense]
FROM cteCalendar c
LEFT JOIN #Expenditure e ON c.MyDate = e.TranDate
AND e.SupplierID = #Supplier
AND e.MOP = #MOP
GROUP BY c.MyDate
) x;
Here is a demo of the code.

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

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)

How to Convert Long into DateTime?

I want to store date time into database table with column type bigint, as given below
DECLARE #temp TABLE (dt BIGINT);
INSERT INTO #temp (dt)
SELECT (20151201190350100)
UNION
SELECT (2015120290350100)
UNION
SELECT (20151203190350100)
UNION
SELECT (20151204190350100)
UNION
SELECT (20151205190350100)
UNION
SELECT (20151206190350100)
SELECT *
FROM #temp
WHERE dt BETWEEN 2015120290350100
AND 20151205190350100
The date as 2015 12 05 19 03 50 100
I need to use WHERE clause, Is it a good approach if I use to save and reactive datetime, please share if you have any better technique.
The answer to your question is:
Just use a datetime data type to store date time values. It will be simpler for many reasons.
CREATE TABLE #temp ( dt DATETIME );
INSERT INTO #temp
( dt
)
SELECT ( '20151201 19:03:50:100' )
UNION
SELECT ( '20151202 09:03:50:100' )
UNION
SELECT ( '20151203 19:03:50:100' )
UNION
SELECT ( '20151204 19:03:50:100' )
UNION
SELECT ( '20151205 19:03:50:100' )
UNION
SELECT ( '20151206 19:03:50:100' )
SELECT *
FROM #temp
WHERE dt BETWEEN '20151202 09:03:50:100'
AND '20151205 19:03:50:100'
DROP TABLE #temp
Note: in your sample values you have lost a few 0's at the start of the hour values, where the time is 09:03:50 - your value is 90350, missing the zero. I have corrected these mistakes in this sample.
DECLARE #temp TABLE (
dt BIGINT,
val AS CAST(STUFF(STUFF(STUFF(STUFF(CAST(dt AS VARCHAR), 9, 0, ' '), 12, 0, ':'), 15, 0, ':'), 18, 0, ':') AS DATETIME)
)
INSERT INTO #temp (dt)
VALUES
(20151201190350100)
, (20151202090350100)
, (20151203190350100)
, (20151204190350100)
, (20151205190350100)
, (20151206190350100)
SELECT *
FROM #temp
WHERE val BETWEEN '2015-12-01 19:03:50.100' AND '2015-12-05 19:03:50.100'
results -
dt val
-------------------- -----------------------
20151201190350100 2015-12-01 19:03:50.100
20151202090350100 2015-12-02 09:03:50.100
20151203190350100 2015-12-03 19:03:50.100
20151204190350100 2015-12-04 19:03:50.100
20151205190350100 2015-12-05 19:03:50.100
add computed column -
ALTER TABLE dbo.tbl
ADD val AS CAST(STUFF(STUFF(STUFF(STUFF(CAST(dt AS VARCHAR), 9, 0, ' '), 12, 0, ':'), 15, 0, ':'), 18, 0, ':') AS DATETIME) --PERSISTED

Resources