SQL Insert Into Select Statement With Condition [closed] - sql-server

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have a table like this :
I want to insert into detail_salary_table with Insert into Select statement.
I can insert the salary_component item "Salary" with this code
INSERT INTO detail_salary_table (date_work, id_emp, salary_component, nominal)
SELECT
date_work, id_emp, 'Salary',
IIF(DATEDIFF(minute, start_work, finish_work) > 480, 10000, round(convert(float(53), datediff(minute, start_work, finish_work)) / 480, 1) * 10000)
FROM
attendance_table
How to insert the salary_component item "OverTime" with T-SQL like the image?
If I use VB.NET, I can do it with if and loop statement.
Note :
480 is fix. 10.000 is fix.
overtime = finish_work - start_work - 480. It take nominal from overtime_rate_table where the value near to time_in_minutes
the increment of nominal in overtime_rate_table is not measured. (so, i cannot use * 1000) (example is measured)
The SQL code to create the tables and sample data:
create table employee_table
(
id_emp int primary key,
name_emp varchar(200)
);
GO
create table attendance_table
(
id_data int primary key identity(1,1),
date_work date,
id_emp int,
start_work datetime,
finish_work datetime
);
GO
create table overtime_rate_table
(
id_data int,
time_in_minutes int,
nominal money
);
GO
create table detail_salary_table
(
id_data int primary key identity(1,1),
date_work date,
id_emp int,
salary_component varchar(100),
nominal money
);
GO
insert into employee_table
values (1, 'Emp A'), (2, 'Emp B'), (3, 'Emp C'), (4, 'Emp D'), (5, 'Emp E');
GO
insert into attendance_table (date_work, id_emp, start_work, finish_work)
values
('2017-02-01',1,'2017-02-01 08:00','2017-02-01 16:52'),
('2017-02-01',2,'2017-02-01 07:45','2017-02-01 16:48'),
('2017-02-01',3,'2017-02-01 08:02','2017-02-01 12:05'),
('2017-02-01',4,'2017-02-01 07:56','2017-02-01 16:49'),
('2017-02-01',5,'2017-02-01 07:30','2017-02-01 18:05'),
('2017-02-02',1,'2017-02-02 07:52','2017-02-02 16:23'),
('2017-02-02',2,'2017-02-02 07:19','2017-02-02 18:56'),
('2017-02-02',3,'2017-02-02 07:55','2017-02-02 18:23'),
('2017-02-02',4,'2017-02-02 08:01','2017-02-02 16:01'),
('2017-02-02',5,'2017-02-02 07:31','2017-02-02 16:49'),
('2017-02-03',1,'2017-02-03 07:52','2017-02-03 17:44'),
('2017-02-03',2,'2017-02-03 07:41','2017-02-03 17:23'),
('2017-02-03',3,'2017-02-03 07:06','2017-02-03 17:56'),
('2017-02-03',4,'2017-02-03 07:56','2017-02-03 19:00'),
('2017-02-03',5,'2017-02-03 07:45','2017-02-03 18:56');
GO
insert into overtime_rate_table
values (1, 15, 1000), (2, 30, 2000), (3, 45, 3000),
(4, 60, 4000), (5, 75, 5000), (6, 90, 6000),
(7, 105, 7000), (8, 120, 8000), (9, 135, 9000),
(10, 150, 10000), (11, 165, 11000), (12, 180, 12000),
(13, 195, 13000), (14, 210, 14000), (15, 225, 15000);
GO

INSERT INTO detail_salary_table
(date_work,
id_emp,
salary_component,
nominal
)
SELECT date_work,
id_emp,
'OverTime',
ISNULL(o.Nominal, 0)
FROM attendance_table a
LEFT JOIN overtime_rate_table o ON CONVERT( INT, DATEDIFF(minute, a.start_work, a.finish_work) - 480) / 15 * 15 = o.time_in_minutes;

Related

Getting duplicate rows in SQL Server

The screenshot contains of 3 tables all connected with other
The second screenshot shows the SQL query and the result obtained:
Query:
SELECT DISTINCT
t.topic_id
, t.topic_name
, t.topic_cover
, t.topic_viewers
, t1.subscribe_id
FROM
tbltopic t
INNER JOIN
tblsubject_grade tg ON (t.subject_garde_id = tg.subject_garde_id)
INNER JOIN
tblsubcription t1 ON (tg.subject_garde_id = t1.subject_garde_id)
The real issue is you have multiple JOIN conditions across a couple of tables
Check this image:
You ll see that table tblsubject_grade JOINS to BOTH the other tables.
Youre query should be:
if OBJECT_ID('tempdb..#topic') IS NOT NULL DROP TABLE #topic
if OBJECT_ID('tempdb..#subjGrade') IS NOT NULL DROP TABLE #subjGrade;
if OBJECT_ID('tempdb..#subscription') IS NOT NULL DROP TABLE #subscription;
CREATE TABLE #topic (topic_id int, topic_name varchar(20), topic_cover varchar(20), topic_viewers int, teacher_id int, subject_garde_id int);
CREATE TABLE #subjGrade (subject_garde_id INT, grade_id INT, subject_id INT);
CREATE TABLE #subscription (subscribe_id INT, sub_status INT, sub_date date, student_id INT, archive_status INT, teacher_id int, subject_garde_id int);
INSERT INTO #topic (topic_id, topic_name, topic_cover, topic_viewers, teacher_id, subject_garde_id)
VALUES
(4, 'numbers', 'somestring', 0,2,1),
(6, 'shapes', 'somestring', 0,9,1),
(7, 'story time', 'somestring', 0, 2, 5)
INSERT INTO #subjGrade (subject_garde_id , grade_id , subject_id)
VALUES
(1, 1, 1),
(2, 1, 2),
(3, 1, 3),
(4, 2, 1),
(5, 2, 2),
(6, 2, 3),
(7, 2, 4),
(8, 3, 1)
INSERT INTO #subscription (subscribe_id, sub_status, sub_date, student_id, archive_status , teacher_id , subject_garde_id)
VALUES
(2, 1, '9-7-2021', 1,0,9,1),
(3, 1, '9-7-2021', 1,0,2,1)
SELECT
t.topic_id
, t.topic_name
, t.topic_cover
, t.topic_viewers
, t1.subscribe_id
FROM #topic t
INNER JOIN #subjGrade tg ON t.subject_garde_id = tg.subject_garde_id
INNER JOIN #subscription t1 ON
tg.subject_garde_id = t1.subject_garde_id
AND t1.subject_garde_id = t.subject_garde_id
AND t.teacher_id = t1.teacher_id

How to remove redundant conditions in **IN** query Sql

I have this kind of query. But i need to optimize this query so how can omit redundant conditions with same split function.
DECLARE #Filter nvarchar(20)
SELECT #Filter ='5,22,3'
SELECT * FROM Employee e
WHERE e.code IN
(
CASE WHEN((SELECT count(*) FROM dbo.FNSPLITSTRING(SUBSTRING(#Filter,1,LEN(#Filter)-1), ',') d
WHERE d.splitdata IN (5, 16, 20, 23, 33, 49, 62, 90, 91, 92, 93, 94))>0) THEN 5 ELSE 0 END
,CASE WHEN((SELECT count(*) FROM dbo.FNSPLITSTRING(SUBSTRING(#Filter,1,LEN(#Filter)-1), ',') d
WHERE d.splitdata IN (22, 18))>0) THEN 46 ELSE 0 END
,CASE WHEN((SELECT count(*) FROM dbo.FNSPLITSTRING(SUBSTRING(#Filter,1,LEN(#Filter)-1), ',') d
WHERE d.splitdata IN (3, 28))>0) THEN 3 ELSE 0 END
)
As #Damien_The_Unbeliever said, avoid split strings as table of values. You do not need to split the same string multiple times. Instead you can use a temporary table variable.
DECLARE #SplitStrings TABLE
(
splitdata int
)
INSERT #SplitStrings
SELECT splitdata FROM dbo.FNSPLITSTRING(SUBSTRING(#Filter,1,LEN(#Filter)-1), ',') d
DECLARE #EmployeeCodes TABLE
(
splitdata INT,
code int
)
INSERT #EmployeeCodes (splitdata, code)
VALUES (5, 5), (16, 5), (20, 5), (23, 5), (33, 5), (49, 5), (62, 5), (90, 5), (91, 5), (92, 5), (93, 5), (94, 5),
(22, 46), (18, 46),
(3, 3), (28, 3)
SELECT e.*
FROM Employee e
JOIN #EmployeeCodes ec
ON e.code = ec.code
JOIN #SplitStrings ss
ON ec.splitdata = ss.splitdata
I hope this is the direction you are looking at.
Note: Assuming that you do not need 0 as employee code.
I have done new way. Less complex and omit redundant code.
DECLARE #Filter nvarchar(20)
SELECT #Filter ='5,22,3'
SELECT Distinct e.EmployeeId FROM Employee e
CROSS JOIN dbo.fnSplitString(#Filter, ',') AS d
WHERE
(e.code = 5 AND d.splitdata IN ('5', '16', '20', '23', '33', '49', '62', '90', '91', '92', '93', '94'))
OR (e.code = 46 AND d.splitdata IN ('22', '18'))
OR (e.code = 3 AND d.splitdata IN ('3', '28'))

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)

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

Deleting records from SQL Server table without cursor

I am trying to selectively delete records from a SQL Server 2005 table without looping through a cursor. The table can contain many records (sometimes > 500,000) so looping is too slow.
Data:
ID, UnitID, Day, Interval, Amount
1 100 10 21 9.345
2 100 10 22 9.367
3 200 11 21 4.150
4 300 11 21 4.350
5 300 11 22 4.734
6 300 11 23 5.106
7 400 13 21 10.257
8 400 13 22 10.428
Key is: ID, UnitID, Day, Interval.
In this example I wish to delete Records 2, 5 and 8 - they are adjacent to an existing record (based on the key).
Note: record 6 would not be deleted because once 5 is gone it is not adjacent any longer.
Am I asking too much?
See these articles in my blog for performance detail:
SQL Server: deleting adjacent values
SQL Server: deleting adjacent values (improved)
The main idea for the query below is that we should delete all even rows from continuous ranges of intervals.
That is, if for given (unitId, Day) we have the following intervals:
1
2
3
4
6
7
8
9
, we have two continuous ranges:
1
2
3
4
and
6
7
8
9
, and we should delete every even row:
1
2 -- delete
3
4 -- delete
and
6
7 -- delete
8
9 -- delete
, so that we get:
1
3
6
8
Note that "even rows" means "even per-range ROW_NUMBER()s" here, not "even values of interval".
Here's the query:
DECLARE #Table TABLE (ID INT, UnitID INT, [Day] INT, Interval INT, Amount FLOAT)
INSERT INTO #Table VALUES (1, 100, 10, 21, 9.345)
INSERT INTO #Table VALUES (2, 100, 10, 22, 9.345)
INSERT INTO #Table VALUES (3, 200, 11, 21, 9.345)
INSERT INTO #Table VALUES (4, 300, 11, 21, 9.345)
INSERT INTO #Table VALUES (5, 300, 11, 22, 9.345)
INSERT INTO #Table VALUES (6, 300, 11, 23, 9.345)
INSERT INTO #Table VALUES (7, 400, 13, 21, 9.345)
INSERT INTO #Table VALUES (8, 400, 13, 22, 9.345)
INSERT INTO #Table VALUES (9, 400, 13, 23, 9.345)
INSERT INTO #Table VALUES (10, 400, 13, 24, 9.345)
INSERT INTO #Table VALUES (11, 400, 13, 26, 9.345)
INSERT INTO #Table VALUES (12, 400, 13, 27, 9.345)
INSERT INTO #Table VALUES (13, 400, 13, 28, 9.345)
INSERT INTO #Table VALUES (14, 400, 13, 29, 9.345)
;WITH rows AS
(
SELECT *,
ROW_NUMBER() OVER
(
PARTITION BY
(
SELECT TOP 1 qi.id AS mint
FROM #Table qi
WHERE qi.unitid = qo.unitid
AND qi.[day] = qo.[day]
AND qi.interval <= qo.interval
AND NOT EXISTS
(
SELECT NULL
FROM #Table t
WHERE t.unitid = qi.unitid
AND t.[day] = qi.day
AND t.interval = qi.interval - 1
)
ORDER BY
qi.interval DESC
)
ORDER BY interval
) AS rnm
FROM #Table qo
)
DELETE
FROM rows
WHERE rnm % 2 = 0
SELECT *
FROM #table
Update:
Here's a more efficient query:
DECLARE #Table TABLE (ID INT, UnitID INT, [Day] INT, Interval INT, Amount FLOAT)
INSERT INTO #Table VALUES (1, 100, 10, 21, 9.345)
INSERT INTO #Table VALUES (2, 100, 10, 22, 9.345)
INSERT INTO #Table VALUES (3, 200, 11, 21, 9.345)
INSERT INTO #Table VALUES (4, 300, 11, 21, 9.345)
INSERT INTO #Table VALUES (5, 300, 11, 22, 9.345)
INSERT INTO #Table VALUES (6, 300, 11, 23, 9.345)
INSERT INTO #Table VALUES (7, 400, 13, 21, 9.345)
INSERT INTO #Table VALUES (8, 400, 13, 22, 9.345)
INSERT INTO #Table VALUES (9, 400, 13, 23, 9.345)
INSERT INTO #Table VALUES (10, 400, 13, 24, 9.345)
INSERT INTO #Table VALUES (11, 400, 13, 26, 9.345)
INSERT INTO #Table VALUES (12, 400, 13, 27, 9.345)
INSERT INTO #Table VALUES (13, 400, 13, 28, 9.345)
INSERT INTO #Table VALUES (14, 400, 13, 29, 9.345)
;WITH source AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY unitid, day ORDER BY interval) rn
FROM #Table
),
rows AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY unitid, day, interval - rn ORDER BY interval) AS rnm
FROM source
)
DELETE
FROM rows
WHERE rnm % 2 = 0
SELECT *
FROM #table
I don't think what you're asking for is possible — but you may be able to get close. It appears you can almost do it by finding records with a self-join like this:
SELECT t1.id
FROM
table t1 JOIN table t2 ON (
t1.unitid = t2.unitid AND
t1.day = t2.day AND
t1.interval = t2.interval - 1
)
but the problem is, that'll find id=6 as well. However, if you create a temporary table from this data, it may be much smaller than your original data, and thus far faster to scan with a cursor (to fix the id=6 problem). You can then do a DELETE FROM table WHERE id IN (SELECT id FROM tmp_table) to kill the rows.
There may be a way to fix the ID=6 problem w/o a cursor, but if so, I don't see it.
There is the WHILE statement, which is an alternative to the cursor. That combined with table variables might let you do the same thing within a performance bound you're OK with.
DECLARE #Table TABLE (ID INT, UnitID INT, [Day] INT, Interval INT, Amount FLOAT)
INSERT INTO #Table VALUES (1, 100, 10, 21, 9.345)
INSERT INTO #Table VALUES (2, 100, 10, 22, 9.367)
INSERT INTO #Table VALUES (3, 200, 11, 21, 4.150)
INSERT INTO #Table VALUES (4, 300, 11, 21, 4.350)
INSERT INTO #Table VALUES (5, 300, 11, 22, 4.734)
INSERT INTO #Table VALUES (6, 300, 11, 23, 5.106)
INSERT INTO #Table VALUES (7, 400, 13, 21, 10.257)
INSERT INTO #Table VALUES (8, 400, 13, 22, 10.428)
DELETE FROM #Table
WHERE ID IN (
SELECT t1.ID
FROM #Table t1
INNER JOIN #Table t2
ON t2.UnitID = t1.UnitID
AND t2.Day = t1.Day
AND t2.Interval = t1.Interval - 1
LEFT OUTER JOIN #Table t3
ON t3.UnitID = t2.UnitID
AND t3.Day = t2.Day
AND t3.Interval = t2.Interval - 1
WHERE t3.ID IS NULL)
SELECT * FROM #Table
Lieven is so close - it worked for the test set, but if I add a few more records it starts to miss some.
We cannot use any odd/even criteria - we have no idea how the data falls.
Add this data and retry:
INSERT #Table VALUES (9, 100, 10, 23, 9.345)
INSERT #Table VALUES (10, 100, 10, 24, 9.367)
INSERT #Table VALUES (11, 100, 10, 25, 4.150)
INSERT #Table VALUES (12, 100, 10, 26, 4.350)
INSERT #Table VALUES (13, 300, 11, 25, 4.734)
INSERT #Table VALUES (14, 300, 11, 26, 5.106)
INSERT #Table VALUES (15, 300, 11, 27, 10.257)
INSERT #Table VALUES (16, 300, 11, 29, 10.428)

Resources