SQL Query Subtracting Values from Two Tables - sql

I have two tables, demand and fte, that have department, shift and demand or fte. I need to calculate the need (demand - fte). What I get is a table with 9 entries. I've run into this before and for the life of me I cannot remember how I resolved it.
There is also a department table which I neglected. It only holds the departmentID & Name
select
dp.[Department], dm.[shift], (dm.Demand - ft.fte) as Need
from
tblDemand dm
right join
[tblDepartment] dp on dp.[DepartmentID] = dm.[DepartmentID]
right join
[tblActual_FTE] ft on ft.[DepartmentID] = dm.[DepartmentID]
where
dp.Department = 'screw ii'
Demand
department
shift
demand
A1
1
23
A1
2
26
A1
3
21
FTE
department
shift
fte
A1
1
26
A1
2
24
A1
3
18
Expected result:
department
shift
need
A1
1
-3
A1
2
2
A1
3
3
Current results:
department
shift
need
A1
1
-3
A1
2
0
A1
3
-5
A1
1
-1
A1
2
2
A1
3
-3
A1
1
5
A1
2
8
A1
3
3

your join should be based on departmentid and shift :
select
dp.[Department]
, dm.[shift]
, (dm.Demand - ft.fte) as Need
from tblDemand dm
right join [tblDepartment] dp on dp.[DepartmentID] = dm.[DepartmentID]
right join [tblActual_FTE] ft
on ft.[DepartmentID] = dm.[DepartmentID]
and ft.[shift] = dm.[shift]
where dp.Department = 'screw ii'

Related

How can I separate a sum of widgets ordered by a vendor when I am using the select sum in a subquery? I tried group by and it still only gives total

I am trying to separate the sums in a sub query with a group by and I have three tables. I have included my current query below and tables I am using.
SELECT DISTINCT
st.stocknumber,
st.locationnumber,
P3.vendornumber,
(
SELECT SUM
( P2.orderquantity )
FROM
PH2 P2
LEFT OUTER JOIN PH1 P1 ON P1.ponumber = P2.ponumber
WHERE
p1.dateordered BETWEEN '10/13/2021'
AND '10/13/2022'
AND p2.location = 'A1'
AND p2.stocknumber = ST.stocknumber
Group BY p2.vendornumber
) As PHOrderQty
FROM
stok ST
left outer join PH2 P3 on (ST.stocknumber = P3.stocknumber)
WHERE
ST.location = 'A1'
AND ST.stocknumber IN (
'22-2552'
'JW00',
'JS20FT',
'JW090'
)
ORDER BY
stocknumber
Data looks like this
Stock Table - ST
stocknumber
location
22-2552
A1
PO Head Table - PH1
n/a
location
dateordered
ponumber
NULL
A1
10/14/2022
1
NULL
A1
10/14/2022
2
NULL
A1
10/14/2022
3
NULL
A1
10/14/2022
4
PO Details Table - PH2
stocknumber
quantityordered
vendornumber
ponumber
22-2552
3
15
1
22-2552
2
20
2
22-2552
1
15
3
22-2552
4
20
4
I keep getting back
stocknumber
location
vendornumber
PHorderQty
22-2552
A1
15
10
22-2552
A1
20
10
What I should be getting back is
stocknumber
location
vendornumber
PHorderQty
22-2552
A1
15
4
22-2552
A1
20
6
Try with the following one:
SELECT ST.stocknumber,
PH1.location,
PH2.vendornumber,
SUM(PH2.quantityordered) AS phOrderQty
FROM stock ST
INNER JOIN head PH1
ON PH1.location = PH1.location
INNER JOIN details PH2
ON ST.stocknumber = PH2.stocknumber
AND PH1.ponumber = PH2.ponumber
WHERE ST.stocknumber IN ('22-2552', 'JW00', 'JS20FT', 'JW090')
AND PH1.location = 'A1'
GROUP BY ST.stocknumber,
PH1.location,
PH2.vendornumber
Check the demo here.

SQL | Join two tables and get one of the tables column against any of the matching row

Table A stores site-article wise transfer/transit stock.
Table A
site article transfer_Stock transit stock
s1 a1 10 15
s1 a2 20 25
Table B has site-article-storage location wise stock
Table B
site article sloc stock
s1 a1 1000 5
s1 a1 2000 10
s1 a1 3000 15
s1 a2 1000 20
s1 a2 5000 25
I want to get total stock as for site article
Output required -
site article sloc transfer_stock transit_stock stock
s1 a1 1000 10 15 5
s1 a1 2000 0 0 10
s1 a1 3000 0 0 15
s1 a2 1000 20 25 20
s1 a2 5000 0 0 25
I want transfer stock and transit stock against any of the row of sloc.
Table A has 1 billion rows and Table B has 1.5 billion rows.
what is the optimised way to achieve this in sql.
Currently we are achieving this throguh
SELECT A.site,
A.article,
B.sloc,
case when MIN_B.sloc=B.sloc then A.transfer_stock else 0 end as transfer_stock,
case when MIN_B.sloc=B.sloc then A.transit_stock else 0 end as transit_stock,
B.stock
FROM A
LEFT OUTER JOIN B ON A.site = B.site AND A.article = B.article
LEFT OUTER JOIN (select site,article,min(sloc) from B group by site,article) MIN_B on A.site = MIN_B.site AND A.article = MIN_B.article
SELECT A.site, A.article, B.sloc, A.transfer_stock, A.transit_stock, B.stock
FROM A
LEFT JOIN B ON A.site == B.site AND A.article == B.article;

Hiding a row where value = 0 but count its other column values in total calculations - sql2008

I have tables like that: (C1-C2 varchar(10), C3-Number int)
WaitingData
C1 C2 C3 Number
A B 1 10
A B 2 0
A B 3 4
X B 4 2
CompletedData
C1 C2 C3 Number
A B 1 5
A B 2 2
A B 3 0
X B 4 12
I am using the query below to represent the data:
Select wd.C1,wd.C2,wd.C3,wd.Number as NW,cdd.Number as NC
into #AllData
from (Select C1,C2,C3,sum(Number) from WaitingData group by C1,C2,C3) wd
outer apply (Select C1,C2,C3,sum(Number)
from CompletedData cd
where wd.C1=cd.C1 and wd.C2=cd.C2 and wd.C3=cd.C3
) cdd
Select * from #AllData
union
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NW)
from #AllData
This is giving me an output like:
C1 C2 C3 NW NC
A B 1 10 5
A B 2 0 2
A B 3 4 0
X B 4 2 12
Total Total -1 16 19
However, I want to hide the rows that has no NW but calculate its regarding values while calculating the Total row (see NC below). The output I want is like:
C1 C2 C3 NW NC
A B 1 10 5
A B 3 4 0
X B 4 2 12
Total Total -1 16 19
I could not find a way to provide an output like this. Any help would be so appreciated!
------------------------------EDIT---------------------------------------
------------------------------EDIT---------------------------------------
When I have data in the tables like below, the outer apply is not working like I want, it does not include the data A B 2.
WaitingData
C1 C2 C3 Number
A B 1 10
A B 3 4
X B 4 2
CompletedData
C1 C2 C3 Number
A B 1 5
A B 2 2
X B 4 12
And the output would be like:
C1 C2 C3 NW NC
A B 1 10 5
A B 3 4 NULL
X B 4 2 12
Total Total -1 16 17
In this situation, what can I do to count "2" NC value having by A B 2 on the final result and see NC as 19 instead 17, except inserting all the records that included by CompletedData but WaitingData? (need an efficient way)
Wrap the final result with one more select and exclude rows where NW = 0.
select * from
(
Select * from #AllData
union
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NC)
from #AllData
) t
where NW <> 0
Edit: Using a full join to get all values from both tables.
with t as
(select coalesce(w.c1,c.c1) as c1,coalesce(w.c2,c.c2) as c2,coalesce(w.c3,c.c3) as c3
, coalesce(w.number,0) as nw , coalesce(c.number,0) as nc
from waitingdata w
full join completeddata c on w.c1 = c.c1 and w.c2=c.c2 and w.c3=c.c3)
select * from
(select * from t
union all
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NC)
from t) x where nw <> 0
You can do all of this in one query, without temporary tables, intermediate results, subqueries, or UNION by using the ROLLUP operator:
SELECT
WD.C1,
WD.C2,
WD.C3,
SUM(WD.Number) AS NW,
SUM(CD.Number) AS NC
FROM
dbo.WaitingData WD
LEFT OUTER JOIN CompletedData CD ON
CD.C1 = WD.C1 AND
CD.C2 = WD.C2 AND
CD.C3 = WD.C3
GROUP BY
WD.C1,
WD.C2,
WD.C3
WITH ROLLUP
HAVING
GROUPING_ID(WD.C1, WD.C2, WD.C3) IN (0, 7) AND
SUM(WD.Number) <> 0

Merging two sql queries columns into one

I have two queries that return:
Query 1
ClassName1 Students1 Teachers1
A1 30 3
A2 20 3
A3 35 4
Query 2
ClassName2 Students2 Teachers2
A1 20 3
A2 22 3
A3 20 4
Result
ClassName1 Students1 Teachers1 ClassName2 Students2 Teachers2
A1 30 3 A1 20 3
A2 20 3 A2 22 3
A3 35 4 A3 20 4
I would like to merge the two dataset into one by columns. SQL 2008
Any ideas?
You would normally do this with a join:
select q1.*, q2.*
from (query1) q1 join
(query2) q2
on q1.ClassName1 = q2.ClassName2;
Thanks i worked this out using this :
**/***********Join **************
select emp.EmpID,emp.FirstName ,emp.LastName,sod.EmpID,sod.HireDate from Employee as emp
join
(
select emp2.EmpID,emp2.HireDate from Employee as emp2
--where emp.EmpID=emp2.EmpID
) sod
on sod.EmpID=emp.EmpID
**/***********cross Apply **************
select emp.EmpID,emp.FirstName ,emp.LastName,sod.EmpID,sod.HireDate from Employee as emp
cross apply
(
select emp2.EmpID,emp2.HireDate from Employee as emp2
where emp.EmpID=emp2.EmpID
) as sod
Any other ideas will be great

Show COUNT of each possible grade for an employee, showing zero when there are no grade entries

I have only one table available. I want to show the grade and the count of the number of times an employee has that grade recorded, but it must show a 0 for the grade if there are no records for that employee. I know how to do this using left join when two tables are present, but I only have 1 table.
How is this possible?
For example:
TABLE
empID | dept | grade
1 | 11 | a
2 | 11 | a
3 | 11 | b
1 | 22 | c
2 | 22 | f
3 | 22 | d
1 | 33 | a
2 | 33 | a
3 | 33 | a
If I run SELECT grade, count(grade) from table where empID = 1 Group by grade;, for example, it ends up printing out only grades the employee got and the count. Now I want to also print out the 0s for grades the employee did not have.
i think you're asking for this?
SQL> select e.grade, count(e2.empid)
2 from (select distinct grade from e) e
3 left outer join e e2
4 on e2.grade = e.grade
5 and e2.empid = 1
6 group by e.grade
7 order by grade;
G COUNT(E2.EMPID)
- ---------------
a 2
b 0
c 1
d 0
f 0
or as you have no rows with "e" grade then if you have a lookup table called grade:
SQL> select * from grade;
G
-
a
b
c
d
e
f
SQL> select e.grade, count(e2.empid)
2 from grade emp
3 left outer join emp e2
4 on e2.grade = e.grade
5 and e2.empid = 1
6 group by e.grade
7 order by grade;
G COUNT(E2.EMPID)
- ---------------
a 2
b 0
c 1
d 0
e 0
f 0
Let's say your query to select a value is:
select value from tbl;
You can ensure a 0 is returned if there are no rows in tbl t:
select nvl(t.value, 0) value
from dual d
left join tbl t on 1=1;
Sounds like you want the NVL function. With NVL, you can conditionally return an alternate value if the value is null. See the documentation.
So, if you had the following...
SELECT fooName, fooNumber FROM foo
and these were your results
fooName, fooNumber
Blah, 1
Asdf, null
Qwer, 3
poiu, null
you could rewrite the query like this...
SELECT fooName, NVL(fooNumber, 0) FROM foo
and your results would now be...
fooName, fooNumber
Blah, 1
Asdf, 0
Qwer, 3
poiu, 0
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions105.htm