insert duplicate rows in temp table - sql

i'm a new to sql & forum - need help on how to insert duplicate rows in temp table. Would like to create a view as result
View - Employee:
Name Empid Status Manager Dept StartDate EndDate
AAA 111 Active A111 Cashier 2015-01-01 2015-05-01
AAA 111 Active A222 Sales 2015-05-01 NULL
I don't know how to write a function, but do have a DATE table.
Date Table: (365 days) goes up to 2018
Date Fiscal_Wk Fiscal_Mon Fiscal_Yr
2015-01-01 1 1 2015
Result inquiry
How do i duplicate rows for each record from Employee base on each of the start date for entire calendar year.
Result:
Name Empid Status Manager Dept Date FW FM FY
AAA 111 Active A111 Cashier 2015-01-01 1 1 2015
AAA 111 Active A111 Cashier 2015-01-02 1 1 2015
******so on!!!!!!
AAA 111 Active A222 Sales 2015-05-01 18 5 2015
AAA 111 Active A222 Sales 2015-05-02 18 5 2015
******so on!!!!!!
Thanks in advance,
Quinn

Select * from Employee cross join Calendar.
This will essentially join every record in calendar to every record in Employee.
so, if there are 2 records in Employee and 10 in calendar, you'll end up with 20 total, 10 for each.

What you are looking for is a join operation. However, the condition for the join is not equality, because you want all rows that match between two values.
The basic idea is:
select e.*, c.date
from employee e join
calendar c
on e.startdate >= c.date and
(e.enddate is null or c.date <= e.enddate);

modified query - this yields result of previous & most recent records
select e.*, c.date, c.FW, c.FM, c.FY
from employee e
join calendar c
on e.startdate <= c.date and
ISNULL(e.enddate,GETDATE()) > c.date

Related

query to find the records between two tables for a given date range

I have a employee table which holds the information about which department the employee belongs during a period of time. At any point in a time a employee can belong to only one department. The end date column holds till what date the employee had stayed in a particular department. if the end date column holds a future date which means thats the latest department for a employee.
empid
deptname
startdate
enddate
1
sales
jan-20-2022
jan-24-2022
1
marketing
jan-25-2022
feb-03-2022
1
support
feb-04-2022
feb-06-2022
1
training
feb-07-2022
dec-31-2050
I have a call details table which holds the information of which employee took the call and what is call start time and call end time.
call_id
empid
callstart_time
callendtime
10
1
jan-21-2022 10:00:00
jan-21-2022 10:30:00
11
1
jan-21-2022 10:40:00
jan-21-2022 10:45:00
12
1
feb-01-2022 11:20:00
feb-01-2022 11:30:00
13
1
feb-05-2022 09:00:00
feb-05-2022 10:00:00
14
1
feb-08-2022 10:00:00
feb-08-2022 11:00:00
Now my question is:
I am looking for inputs and the sample query where i need to know what was the employees department during the time the employee took the call.
For example, if I want to know what are the calls took by an employee from jan-20-2022 to feb-02-2022 and what was there department name during the time of the call. i need the below output.
call_id
empid
callstart_time
callendtime
deptname
10
1
jan-21-2022 10:00:00
jan-21-2022 10:30:00
sales
11
1
jan-21-2022 10:40:00
jan-21-2022 10:45:00
sales
12
1
feb-01-2022 11:20:00
feb-01-2022 11:30:00
marketing
If i run the query for a date range from feb-04-2022 to feb-10-2022, i want to see the below output
call_id
empid
callstart_time
callendtime
deptname
13
1
feb-05-2022 09:00:00
feb-05-2022 10:00:00
support
14
1
feb-08-2022 10:00:00
feb-08-2022 11:00:00
training
please share few inputs on how to achieve this output using the sql query
A CROSS APPLY lets you define a subselect to pick the applicable employee record. In your case, the latest employee record prior to the call. Something like:
SELECT C.*, E.deptname
FROM calldetails C
CROSS APPLY (
SELECT TOP 1 *
FROM employee E
WHERE E.empid = C.empid
AND E.startdate <= C.callstart_time
ORDER BY E.startdate DESC
) E
ORDER BY C.callstart_time
See this db<>fiddle
Or since you have end date, a simple join will do
SELECT C.*, E.deptname
FROM calldetails C
JOIN employee E
ON E.empid = C.empid
AND E.startdate <= C.callstart_time
AND E.enddate > DATEADD(day, -1, C.callstart_time)
ORDER BY C.callstart_time
Note the date adjustment needed for the enddate comparison. This is needed because you are using inclusive enddates, Using exclusive end dates (where enddate = startdate for the next record works much better for range checks and calculations.

Return rows if the column value is different than the previous days record

I want a select query that returns me all rows for the current day, only if the 'amount' is different that the previous days.
sales
-id
-user_id
-amount
-datetime
The sales table gets a new record for each user_id daily.
An example scenerio would be as follows:
5 123 700 2017/01/05
4 123 500 2017/01/04
3 123 1500 2017/01/03
2 123 1500 2017/01/02
1 123 500 2017/01/01
So if you search for records on the Jan. 5th, you will get 1 row since it is different that the previous days (700 vs 500).
result:
5 123 700 2017/01/05
But if you were run the query on the 3rd, since the amound $1500 is the same as on the 2nd, you will get 0 results back.
I have this basic join but I need to somehow compare the current days row from s1 and compare that with the previous days amount value.
select s1.*
from sales as s1
inner join sales s2 on s1.user_id = s2.user_id and s1.datetime = s2.datetime
You basically have the query. You just need the date arithmetic:
select s.*
from sales s left join
sales sprev
on sprev.user_id = s.user_id and sprev.datetime = dateadd(day, -1, s.datetime)
where s.datetime = '2018-01-05' and
(s.amount <> sprev.amount or sprev.amount is null);

to find invalid managers from a table in sql

I have a table :
xx_asg
person_no location org mgr_person_no effective_start_date eff_end_date
1 Mumbai XYZ 101 01-jan-1901 31-DEC-4712
101 Delhi xyz 201 01-JAN-2005 31-DEC-4712
5 Delhi XYZ 1 01-JAN-1901 31-DEC-4712
In this table each person has a manager whose person record is also ther in this table.
But as seen above there are cases like for person no 1 with effective start date 01-jan-1901 but it has a manager person no. 101
whose effective start date is from 01-jan-2005. so this is invalid as from 1901-2005 this manager did not existed.
I want a query to get such cases from this table. Can anyone just guide through the logic
You can use a self join, and check if the manager dates is not in the person dates range, like this:
SELECT * FROM YourTable t
INNER JOIN YourTable s
ON(s.person_no = t.mgr_person_no)
WHERE s.effective_start_date > t.effective_start_date
OR s.effective_end_date < t.effective_end_date
EDIT: If effective_start_date and effective_end_date columns are string and not dates, you have to convert them:
SELECT * FROM YourTable t
INNER JOIN YourTable s
ON(s.person_no = t.mgr_person_no)
WHERE to_date(s.effective_start_date,'dd/mm/yyyy') > to_date(t.effective_start_date,'dd/mm/yyyy')
OR to_date(s.effective_end_date,'dd/mm/yyyy') < to_date(t.effective_end_date,'dd/mm/yyyy')

SQL query to find most recent date using two tables

I have two tables in a database. One called Users and one called Days.
The Users table has a column called ID which contains some numbers and an ActiveUser column which contains either a 0(not active) or 1(active). The Days table has a column called UserID which contains the same numbers the ID column from the Users table has. It also has a column called Day which contains info like "2015-01-01 00:00:00:000".
Users Table:
ID | ActiveUser
-------------------
10 | 0
11 | 1
12 | 1
13 | 0
Days Table:
User_ID | Day
------------------
10 | 2010-06-24 00:00:00.000
11 | 2011-07-05 00:00:00.000
12 | 2008-06-19 00:00:00.000
13 | 2010-06-20 00:00:00.000
10 | 2009-09-02 00:00:00.000
12 | 2010-08-15 00:00:00.000
11 | 2011-05-06 00:00:00.000
13 | 2012-04-25 00:00:00.000
I'm trying to create a query that finds the most recent Day listed for each Active user. So using the tables above, the query I'm trying to make should give me the following:
Day
------
2011-07-05 00:00:00.000
2010-08-15 00:00:00.000
Which corresponds to the two Active users with user ID's 11 and 12, both of which have two entries for Day, but the query picks the most recent date.
I'm new to SQL, and the closest I've got is below, which doesn't take into account the Users table (also, used https://stackoverflow.com/a/2411703/2480598 as a template):
select Days.Day
from Days
inner join (select User_ID, max(day) as MaxDay
from Days
group by User_ID
) tm on Days.User_ID = tm.User_ID and Days.Day = tm.MaxDay
This gives me the list of dates for users active and non-active.
Select a.User_ID, max(a.day) as LatestDay from Days a
Inner Join Users b
on a.User_ID = b.ID and b.ActiveUser = 1
group by a.User_ID
The inner join limits it to active users only. You can remove a.User_ID from the select if you only want a list of days.
This is classic example where APPLY can be applied:
select * from users u
outer apply(select top 1 day from days where userid = u.id order by day desc)a
where u.ActiveUser = 1
If you want only the day column(I think it makes no sense):
select max(d) as day
from users u
join days d on d.userid = u.id
where u.ActiveUser = 1
group by u.id
You need to join to the users table to get the active users. Here is a simple way:
select u.id, max(d.day) as MaxDay
from Days d join
Users u
on d.user_id = u.id
where u.ActiveUser = 1
group by u.User_ID;

How to get columns from second table only if data exists otherwise should return null?

I am struggling with SQL Joins concept and am facing problem when I am trying to get student attendance record. There are 3 tables that have to be used.
attendance a - has all student attendance
st_holiday b, - student specific holiday public list
hol_list c - all holiday list including weekend
There are 2 questions:
1. I need data that gives me in_time, out_time and holiday_type to me. Student can also attend class on his holiday date(can be public holiday or weekend).
I tried below query which gives me only holiday attended dates.
select a.student_id, a.in_time, a.out_time, b.holiday_type
from attendance a, st_holiday b, hol_list c
where a.st_id = b.st_id
and b.holiday = c.id
and a.date = c.hol_date
I have also tried using left outer join st_holiday on a.st_id = b.st_id and left outer join holiday_type on a.date = c.hol_date
But it gives me all data and for each data holiday_type shows as Holiday/weekend, etc.
2. How to parameterize by date. I need to provide the data as sql script with date range parameterized. How to do the same in Sql Server. I tried using
DECLARE from_date='2015-04-01 00:00:00.000'
DECLARE to_date='2015-04-01 00:00:00.000'
SELECT * FROM TABLE
WHERE ....
AND [PI].Date BETWEEN ISNULL(#FromDate, [PI].Date) AND ISNULL(#ToDate, [PI].Date)
I used below link for reference. sql server optional parameters: syntax for between clause
Any help will be appreciated.
Update : Table Structure.
attendance a - primary Key ID, st_id shared with st_holiday table
st_holiday b, - pk is ID, holiday shared with hol_list table
hol_list c - hol_date can be used with date of attendance table.
Expected output:
St_id IN_TIME OUT_TIME Hol_type
1234 2015-08-07 08:00:00.000 2015-08-07 17:00:00.000 null
1234 2015-08-08 08:00:00.000 2015-08-08 08:00:00.000 Weekend
Table structure : st_id in attendance and st_holiday table are not unique. The value will be repeated. For eg. eah st_id in st_holiday will have 20 holidays for very year i.e. st_id is repeated 20 times. In attendance table st_id will depend on no. of times student comes in and goes out of classroom.
attendance
-------------
st_id in_time out_time time_in_class
3370 2009-10-8 11:54:0.0 2009-10-8 18:1:0.0 6.11666666666667
4209 0 0 0
4225 0 0 0
3779 2009-10-8 14:27:0.0 2009-10-9 0:5:0.0 9.63333333333333
hol_list
-------------
id hol_date type desc holiday_type
229 2007-04-06 00:00:00.000 1 Good Friday Holiday
231 2007-05-01 00:00:00.000 1 International Labor Day Holiday
233 2007-07-04 00:00:00.000 1 Independence Day Holiday
234 2007-07-07 00:00:00.000 1 Weekend Weekend
st_holiday
-------------
st_id holiday holiday_type
9201 39965 Holiday
9201 39961 Holiday
9201 39951 Holiday
9201 39942 Holiday
9201 39935 Weekend
9201 39927 Holiday
Based on your sample query and explanation. For your first question, kindly give this a try:
select a.student_id, a.in_time, a.out_time, b.holiday_type
from attendance a
left join st_holiday b on a.st_id = b.st_id
inner join hol_list c on a.date = c.hol_date