How to create this append record? - sql

I have a table full with employees structured as:
tblEmployees
+--------------+------------+-----------+-------+
| EmployeeID | FirstName | LastName | Wage |
+--------------+------------+-----------+-------+
I then have a table which the user can paste data into from an external software which looks like so:
tblImport
+------------+-----------+--------------+
| EmployeeID | WorkDate | HoursWorked |
+------------+-----------+--------------+
This will then go into another table (HoursWorkedRecords) which is structured the same way.
When I append from the import table to the main table what I would like is firstly:
The append to check if the EmployeeID pasted into the tblImport table exists in tblEmployees, if so then it append to HoursWorkedRecords.
Before importing check there are no duplicate records by the EmployeeID on that given WorkDate.
My question is how can I achieve this?

You can use a query to do this. If you use a LEFT JOIN between HoursWorkedRecords and tblEmployees on EmployeeID then any null entries in your employees table will signify hours worked records where the employee could not be found. You can either use this query directly or through a VBA module.
The (untested) SQL for the query is
SELECT
HWR.EmployeeID
FROM HoursWorkedRecords AS HWR
JOIN tblEmployees AS TE
ON HWR.EmployeeID = TE.EmployeeID
WHERE
TE.EmployeeID IS NULL

The answer to your question depends on how you wish to proceed should either of your requirements fail to be met:
What should happen if the EmployeeID is not found in the tblEmployees table?
What should happen if there are duplicates found in the HoursWorkedRecords table?
If the answer to these questions is to simply ignore the records which do not meet the criteria, then this can be achieved with a relatively simply INSERT query:
insert into hoursworkedrecords
select
i.employeeid, i.workdate, i.hoursworked
from
(tblimport i inner join tblemployees e on i.employeeid = e.employeeid)
left join hoursworkedrecords h on i.employeeid = h.employeeid and i.workdate = h.workdate
where
h.employeeid is null
Here, the inner join on the tblEmployees table ensures that the EmployeeID is valid, and the left join on the hoursworkedrecords table in conjunction with the is null criteria ensures that a record for that employee on that date does not exist.
If however, the user should be alerted to these issues, you should use the reverse of the above query to select the invalid records for the user to review before proceeding.

Related

How to tune query to fetch result faster | Oracle 19c |

I have a table which as huge records in table
My tables : employee and customer
Now the issue here is I have 2 billion records in employee table and 1 billion records in customer table
Employee columns
empid
empname
empage
empdcourse
Customer columns
custid
custdesc
custmessage
My query :
select emp_id from employee where empid not in ( select custid from customer);
Error : It throws me table space issue. Not allowed to increase table space
Is their any way I can tune my query or run in batch by batch so I get output
Any solution is much appreciated !!!
Need it on high priority
NOT EXISTS may be more efficient and less memory consuming in such case.
(The query suggests Customer and Employee share the same PK, does it mean you have an "super" table Person ?)
Try this:
with tmp as
(select /*+full(c)*/
custid
from customer c)
select /*+full(e)*/
e.emp_id
from employee e, tmp t
where e.empid = t.custid(+)
and t.custid is null;
The hint full will prevent the tablespace issue.
The OUTER JOIN is faster than the NOT IN.
You can improve it by adding the hint parallel, starting with a degree=2 or 4 like this:
with tmp as
(select /*+full(c) parallel(c,2)*/
custid
from customer c)
select /*+full(e) parallel(e,2)*/
e.emp_id
from employee e, tmp t
where e.empid = t.custid(+)
and t.custid is null;
You can add indexes for columns, for example, if they aren’t primary keys:
CREATE INDEX empid_index
ON employee(empid);
Also, you can update the query:
select e.empid from employee e where not exists (select 1 from customer c where c.custid = e.empid);

How to update a table data that was created using INNER JOIN based on ID (CASE_KEY )?

Basically, what I want to accomplish are to UPDATE the DEPARTMENT_NAME from TV_LABCASE table and to UPDATE the CHARGE from TV_LABCASE table based on CASE_KEY. But I do not know how to update a table that was created using an INNER JOIN
TV_LABCASE table:
CASE_KEY
DEPARTMENTMENT_CASE_NUMBER
DEPARTMENT_NAME
CHARGE
LAB_CASE
OFFENSE DATE
4235
090909
OHIO
STEALING
0123
08/15/2020
4332
131313
CANADA
STEALING
764
08/17/2020
This TV_LABCASE table was queried using this:
SELECT TOP 10
C.CASE_KEY, C.DEPARTMENT_CASE_NUMBER,
D.DEPARTMENT_NAME, O.OFFENSE_DESCRIPTION AS CHARGE,
LAB_CASE, OFFENSE_DATE
FROM
TV_LABCASE C
INNER JOIN
TV_DEPTNAME D ON C.DEPARTMENT_CODE = D.DEPARTMENT_CODE
INNER JOIN
TV_OFFENSE O ON C.OFFENSE_CODE = O.OFFENSE_CODE
ORDER BY
CASE_DATE DESC
TV_DEPTNAME table:
DEPARTMENT_CODE
DEPARTMENT_NAME
100
AMERICA
1000
CANADA
This TV_DEPTNAME table was queried using this:
SELECT *
FROM TV_DEPTNAME
TV_OFFENSE table:
OFFENSE_CODE
OFFENSE_DESCRIPTION
STG
STEALING
ABT
ABORTION
This TV_OFFENSE table was queried using this:
SELECT *
FROM TV_OFFENSE
This is the result in the TV_LABCASE table after the update:
CASE_KEY
DEPARTMENTMENT_CASE_NUMBER
DEPARTMENT_NAME
CHARGE
LAB_CASE
OFFENSE DATE
4235
090909
New Department Name
New Charge
0123
08/15/2020
4332
131313
CANADA
STEALING
764
08/17/2020
You're misunderstanding how relational databases work - the table was not created using an INNER JOIN, you wrote a query that is using an INNER JOIN and the values you said you want to change are coming from the joined tables.
What you want to change with your UPDATE is the values in the TV_LABCASE table DEPARTMENT_CODE and OFFENSE_CODE columns.
When you change their values then they will change which rows are joined by query in future, so for example you could write an update like this
UPDATE TV_LABCASE
SET DEPARTMENT_CODE = 100, OFFENSE_CODE = 'ABT'
WHERE CASE_KEY = 4235
That will result in the values shown in your query result changing from OHIO to AMERICA and from STEALING to ABORTION.
Currently i was working on this type of scenario
Please try this query and adjust param according to your requirement.
UPDATE
ledgers l,
orders O
SET
l.created_at = O.created_at
WHERE
l.order_id = O.id;

How to fetch data from two different tables in SQL

I'm trying to fetch the records from two different tables in the same database. But I encounter an error.
Query:
use AdventureWorks2014
select
cast(departmentID as nvarchar), ModifiedDate
from
[HumanResources].[Department]
union
select
LoginID, JobTitle
from
[HumanResources].[Employee]
Error:
Msg 241, Level 16, State 1, Line 2
Conversion failed when converting date and/or time from character string.
I appreciate your help.
Thanks All
Wild guess, but I am thinking that you are likely trying to get the records from the [HumanResources].[Employee] table and their corresponding department via the [HumanResources].[Department] table.
If this is the case, then I am assuming that there would be a key relationship between the tables. For example, your Employee table could have a DepartmentId column for which you can then perform a join.
Employee Table
LoginId
FirstName
LastName
JobTitle
DepartmentId
Department Table
DepartmentId
DepartmentName
ModifiedDate
Then for a table structure like above, you just need to make a JOIN operation on the table.
SELECT emp.LoginId, emp.FirstName, emp.LastName, dep.DepartmentName
FROM Employee emp
INNER JOIN Department dep ON dep.DepartmentId = emp.DepartmentId
If you can post your table structure and the desired data output, then I am pretty sure we could help you formulate the query better.
You used UNION, so the datatypes of the columns in both select statements should be the same.
And you are fetching the data from the Department and Employee table. Here, you have to use the join between Department and EmployeeDepartmentHistory on DepartmentID and join between EmployeeDepartmentHistory and Employee table on BusinessEntityID to get the columns you have posted.
SELECT
D.DepartmentID
,D.ModifiedDate
,E.LoginID
,E.JobTitle
FROM [HumanResources].[Department] D
INNER JOIN [HumanResources].[EmployeeDepartmentHistory] EDH
ON D.DepartmentID = EDH.DepartmentID
INNER JOIN [HumanResources].[Employee] E
ON EDH.BusinessEntityID = E.BusinessEntityID
Here is the sample:

SQL Server : replace several instances of userID with username

I may be overthinking this but I have not managed to figure it out or find a solution, so I'm hoping for a pointer in the right direction. I tried using the Select ColumnA AS Column B etc but it's not doing what I want.
I have 2 tables, scenario examples below
Table 1 (Vehicle)
VehicleID (001)
VehicleMake (Ford)
VehicleModel (Falcon)
VehicleExCleanEmpID (005)
VehicleIntCleanEmpID (003)
Table 2 (Employee)
EmpID (005)
EmpName (Dave)
The scenario being that a vehicle is cleaned internally or externally by any one of a pool of employees shown by the relevant ID in the Vehicles table.
I want to show in a query VehicleID, InsideCleanName, ExternalCleanName rather than showing the employee's ID.
So end up with results similar to this
VehicleID InsideCleanName ExternalCleanName
------------------------------------------------
001 Bob Dave
002 Sue Dave
003 John Sid
Thanks for any tips and or help
THat seems like a pretty simple query with two inner joins to the Employee table - something like this:
SELECT
v.VehicleId,
InsideCleanName = e1.EmpName,
ExternalCleanName = e2.EmpName
FROM
dbo.Vehicle v
INNER JOIN
dbo.Employee e1 ON v.VehicleIntCleanEmpId = e1.EmpID
INNER JOIN
dbo.Employee e2 ON v.VehicleExCleanEmpId = e2.EmpID
Joining to the Employee e1 table is giving you the employee who was responsible for the inside cleaning, while joining a second time, to Employee e2 gives you the one responsible for the external cleaning.
Join the two table with EmpId and select the columns you want similar to the code below:
select column1, column2 from table1 inner join table2 on table1.EmpId = table2.EmpId

Joining same table multiple times

I have 2 tables Person an Department - where each person has multiple departments registered against him.
Person
id|name|dept1|dept2|dept3
1 |Jane|100 |102 |106
Dept
id |Name
100|Accounts
...
102|HR
...
106|Admin
Whats the most elegant sql to display Jane's record as follows:
Jane|Accounts|HR|Admin
Use this. And work on your naming convention to make all column names unique independent of table.
SELECT
Person.id, Person.name, dept1.Name, dept2.Name, dept3.Name
LEFT JOIN Dept dept1 ON dept1.id = Person.dept1
LEFT JOIN Dept dept2 ON dept2.id = Person.dept2
LEFT JOIN Dept dept3 ON dept3.id = Person.dept3
Something like this will let you join the same table multiple times. You just give each join a different alias
SELECT *
FROM Person AS P
INNER JOIN Dept AS D1 ON P.dept1 = D1.id
INNER JOIN Dept AS D2 ON P.dept2 = D2.id
WHERE P.name = 'Jane'
Ideally you would normalise the data in your Person table and have a linking table between Person and Dept e.g. PersonDepartmentLinking (or whatever convention you have for linking table naming conventions), assuming you have any control over the schema and it's possible to add the relationship that way.
You can use STUFF in this case
Select name,
Stuff((Select distinct ', ' + cast(Name as varchar(20))
From #Dept t2
Where t2.Id = t1.Id
FOR XML PATH('')),1,1,'')
From Person t1
The only way that I know is a join for each column.
But if you are in the way of designing the tables, i suggest you to normalize the DB.
If a person need an extra dept column, you need to alter the table to add a new property of person.
For me, 3 entities are needed:
- Person
- Department
- person_department_assignation