Make a query to display unmatched data - sql

I m having difficulty making a query that displays unmatched data in between 2 tables.
The tables are:
Employee data Salary data
ID Holidays ID Holiday
1 10 0 10
2 8 1 5
3 5 2 8
4 7 3 5
5 8 7 6
6 5 8 9
7 6 9 2
8 9 10 3
the primary key is ID for both tables.
I want my query result to contain all the values that does not match in both tables.
The type of output i want is something like this:
ID Holiday
0 10
1 10
1 5
4 7
5 8
6 5
9 2
10 3
I tried using unmatched query wizard but that only compares ID, not the Holiday column.
Please help me!

You could use a union of two exists queries:
SELECT ID, Holiday FROM Employee as e
WHERE NOT EXISTS (SELECT 1 FROM Salary as s WHERE s.ID = e.ID AND s.Holiday = e.Holiday)
UNION ALL
SELECT ID, Holiday FROM Salary as s
WHERE NOT EXISTS (SELECT 1 FROM Employee as e WHERE e.ID = s.ID AND e.Holiday = s.Holiday);

Related

SQL get all children

So I have hierarchical data that is organized in departments, with each department having a parent department except for the top one. I now want to write a SELECT statement to select this hierarchical structure in a cumulative way. That means that for every level in the hierarchy I want to see all the entries that are children of that.
For example, if I have the following tables:
Departments
ID PARENT_ID
1 null
2 1
3 1
4 2
5 2
6 3
7 3
Employees
ID DEPT
1 2
2 2
3 3
4 4
5 5
6 6
7 7
8 2
9 3
10 4
11 5
12 6
13 7
14 2
15 3
16 4
17 5
I would like to have something like the following result:
ID_E ROOT DEPT
1 null 1
1 1 2
2 null 1
2 1 2
3 null 1
3 1 3
4 null 1
4 1 2
4 2 4
5 null 1
...
I have looked around and fiddled a bit but just cannot get it to work.
I thought this would do the trick but it gives weird results (meaning many duplicate rows):
SELECT connect_by_root(dept.id) AS dept_id,
CONNECT_BY_ROOT(dept.parent_id) AS parent_id,
emp.id AS id_e
FROM emp
RIGHT JOIN dept ON emp.dept = dept.id
CONNECT BY PRIOR dept.id = dept.parent_id
EDIT: Here is a fiddle of the scenario
I came up with a solution, using a recursive CTE to parse the hierarchy and retrieve each possible way a department can connect to the root, which is then joined with the employee table.
Could you give it a try, and let me know if it works?
WITH RCTE_DEPT(id,root,parent_id) AS(
SELECT id,parent_id, id
FROM dept
UNION ALL
SELECT dept.id,root,RCTE_DEPT.parent_id
FROM dept
JOIN RCTE_DEPT ON
dept.parent_ID = RCTE_DEPT.id)
SELECT emp.id as ID_E, RCTE_DEPT.root as ROOT, RCTE_DEPT.parent_id as DEPT
FROM emp
JOIN RCTE_DEPT ON emp.DEPT = RCTE_DEPT.id
ORDER BY ID_E ASC, ROOT ASC, DEPT ASC
Here is a fiddle.

Add up all values in column P that has the same value in column A that come from 2 different tables

I have 2 tables joined and I was wanting to add up the value in the price column with ones that had the same value in the EmployeeID column
EmployeeID Price
2 8
2 5
2 11
2 8
3 6
3 8
5 13
5 16
6 13
8 5
9 10
9 4
Select o.EmployeeID,p.Price
From Orders o
inner join Product p on o.ProductID=p.ProductID
(This is the code I used to display the 2 columns from separate tables.)
EmployeeID Price
2 32
3 14
5 29
6 13
8 5
9 14
This is what I want the table to look like
Consider using group by statement for aggregating values referring to the same attribute. I.e., in your case, the solution might look like
select o.EmployeeID, sum(p.Price)
from Orders o
inner join Product p on o.ProductID=p.ProductID
group by o.EmployeeID

T-SQL get all nodes and their last level children using common table expression

I need the last level children of all nodes between the last level and the parent. I am new to recursive ctes and trying to get this result.
Consider the following table:
emp id | mgr id
1 null
2 1
3 1
4 1
5 2
6 2
7 3
8 3
9 4
10 4
11 5
12 6
13 6
14 6
15 11
if the input is (15) then the output should be
mgr id emp id
2 12
2 13
2 14
2 15
5 15
6 12
6 13
6 14
11 15
Searching around the web I figured this can be done using recursive queries but I am unable to.
with cte as
(
select
emp_id, mgr_id
from
emp_heirarchy
where
emp_id in (select MIN(lt.emp_id)
from landing_table lt
inner join emp_heirarchy eh on lt.emp_id = eh.emp_id
group by mgr_id)
union all
select
eh.emp_id, eh.mgr_id
from
emp_heirarchy eh
inner join
cte c on c.mgr_id = eh.emp_id
)
select distinct *
from cte
order by mgr_id
I have tried a few other versions of the above query with no luck.

SQL Inner Join and Partitioning To obtain RowNumbers when matching

I have 2 tables. The first table 'a' the second 'b'.
I am writing a query that grabs every row in table a (there is 33 rows defined) and inner joins table b where the EnclLocation or the BackPanLoc match the Workcell in table A.
I only want a row from table B where they match based off BackPan and EnclLocation but they are not the same records. table b has a few rows of data that is assigned to the same workcell as table a. I am just trying to retrieve those additional rows and partition it.
I attached table a and table b. I also attached the desired results for this query with respect to Workcell 10 only as an example... As you can see, table B has 4 records that has either the EnclLocation or the BackPanLoc = 10. But my results only show the same DelvNumber 4 times. any help is most appreicated.
Table a
Table b
Incorrect Results
Desired Results (showing only Workcell 10 as an example)
workcell DelvNumber RowNum
1 447910-02 1
2 445710-01 1
2 445710-01 2
3 444291-01 1
3 444291-01 2
4 447910-03 1
4 447910-03 2
5 648020-01 1
6 647800-02 1
7 646920-01 1
7 646920-01 2
8 644830-4-8 1
8 644830-4-8 2
9 443990-01 1
10 645960-01-03 1
10 445710-11 2
10 445710-02 3
10 445710-09 4
Code Used
WITH ss
AS (SELECT a.*,
Row_number()
OVER(
partition BY a.workcell
ORDER BY a.workcell) AS rownum
FROM nwcurrent a
INNER JOIN nwdeliverables b
ON b.encllocation = a.workcell
OR b.backpanloc = a.workcell
WHERE ( b.status < 9
AND ( b.encllocation <> 0
OR b.backpanloc <> 0 )
OR a.delvnumber = '123' ))
SELECT *
FROM ss
copy and paste format
1 447910-02 1
2 445710-01 1
2 445710-01 2
3 444291-01 1
3 444291-01 2
4 447910-03 1
4 447910-03 2
5 648020-01 1
6 647800-02 1
7 646920-01 1
7 646920-01 2
8 644830-4-8 1
8 644830-4-8 2
9 443990-01 1
10 645960-01-03 1
10 445710-11 2
10 445710-02 3
10 445710-09 4
SQLFiddle
http://sqlfiddle.com/#!3/a8682/4
A new try...
SELECT a.workcell
,a.DelvNumber AS A_DelvNumber
,b.DelvNumber AS B_DelvNumber
,CASE WHEN a.DelvNumber<>b.DelvNumber THEN b.DelvNumber ELSE a.DelvNumber END AS DelvNumber_Resolved
,Row_number() OVER(partition BY a.workcell ORDER BY a.workcell) AS rownum
FROM NWCurrent a
INNER JOIN NWDeliverables AS b ON b.EnclLocation=a.WorkCell OR b.BackPanLoc=a.WorkCell
WHERE (b.status <9 AND (b.EnclLocation<>0 OR b.BackPanLoc<>0)OR a.DelvNumber='123')

Query to serialize data

I have two tables:
Routes
ID Description
1 street1
2 street2
3 street3
4 street4
5 street5
Segments
ID RouteID, Progres, LabelStart, LabelEnd
1 1 5 1 A 21 B
2 1 10 2 A 10
3 2 15 3 25
4 2 15 2 20
5 3 20 1 11
6 3 22 4 10
7 4 30 5 11
8 4 31 2 12
I need a sequence with these rules:
table must be ordered by Progress ASC
A column Type is defined and take O if LabelStart and LabelEnd are Odd, E if Even
if two routes have the same progress then the rows are merged in one where
LabelStart is the minimum (among LabelStart Odd and LabelStart Even)
and LabelEnd is the Max, in this case Type takes the value of A (All)
as per example data above the result should be
Sequence
ID RouteID, Progres, LabelStart, LabelEnd Type
1 1 5 1 A 21 B O
2 1 10 2 A 10 E
4 2 15 2 25 A
5 3 20 1 11 O
6 3 22 4 10 E
7 4 30 5 11 O
8 4 31 2 12 E
It is for Postgres 9.2
This was an interesting query to write because you had letters in your LabelStart and LabelEnd fields. I used REGEX_REPLACE to remove those. Then I used a CTE to get the records that had more than one routeid and progress rows.
I think this should do it:
WITH CTE AS (
SELECT
RouteId, Progress
FROM Sequence
GROUP BY RouteId, Progress
HAVING COUNT(DISTINCT Id) > 1
)
SELECT MAX(S.ID) Id,
T.RouteId,
T.Progress,
MIN(regexp_replace(LabelStart, '[^0-9]', '', 'g')) LabelStart,
MAX(regexp_replace(LabelStart, '[^0-9]', '', 'g')) LabelEnd,
'A' as Type
FROM Sequence S
INNER JOIN CTE T ON S.RouteId = T.RouteId AND S.Progress = T.Progress
GROUP BY T.RouteId, T.Progress
UNION
SELECT S.Id,
S.RouteId,
S.Progress,
S.LabelStart,
S.LabelEnd,
CASE
WHEN CAST(regexp_replace(LabelStart, '[^0-9]', '', 'g') as int) % 2 = 0
THEN 'E'
ELSE 'O'
END
FROM Sequence S
LEFT JOIN CTE T ON S.RouteId = T.RouteId AND S.Progress = T.Progress
WHERE T.RouteId IS NULL
ORDER BY Progress ASC
And some sample Fiddle.