need help sql query - sql-server-2005

I am having one query given below in that Employee, ShiftAllocation, ShiftMaster (two for two shift: Shift1 and shift2) table
SELECT
Em.EmployeeId, Em.EmployeeName,
Sa.ShiftAllocationDate, Sa.ShiftId2, Sa.ShiftId, Sm.ShiftName,
Sm2.ShiftName AS ShiftName2, Sa.ShiftAllocationId
FROM
ShiftAllocation AS Sa
INNER JOIN
EmployeeMaster AS Em ON Sa.EmployeeId = Em.EmployeeId
LEFT OUTER JOIN
ShiftMaster AS Sm2 ON Sa.ShiftId2 = Sm2.ShiftId
LEFT OUTER JOIN
ShiftMaster AS Sm ON Sa.ShiftId = Sm.ShiftId
I am getting this output:
ShiftAlld EmployeeId EmployeeName ShiftAllDate shiftId2 ShifId ShiftName ShiftName2
1 19 XYZ 2011-08-01 NULL 1 General NULL
2 19 XYZ 2011-08-02 NULL 1 General NULL
3 19 XYZ 2011-08-02 NULL -1 NULL NULL
4 19 XYZ 2011-08-02 NULL 1 General NULL
5 19 XYZ 2011-08-02 NULL -2 NULL NULL
6 19 XYZ 2011-08-02 NULL 1 General NULL
I want
shiftId -1 value should assign ShiftName as Week Off
ShiftId -2 value should assign ShiftName as Holiday
ShiftId2 NULL value should assign ShiftName2 as Not Assign
I want this output:
ShiftAlld EmployeeId EmployeeName ShiftAllDate shiftId2 ShifId ShiftName ShiftName2
1 19 XYZ 2011-08-01 NULL 1 General NotAssign
2 19 XYZ 2011-08-02 NULL 1 General NotAssign
3 19 XYZ 2011-08-02 NULL -1 WeekOff NotAssign
4 19 XYZ 2011-08-02 NULL 1 General NotAssign
5 19 XYZ 2011-08-02 NULL -2 Holiday NotAssign
6 19 XYZ 2011-08-02 NULL 1 General NotAssign

You can use a case something like this (untested so there may be any number of typos in there).
select Em.EmployeeId,
Em.EmployeeName,
Sa.ShiftAllocationDate,
Sa.ShiftId2,
Sa.ShiftId,
case when sa.ShiftId = -1 then 'Week Off'
when sa.ShiftId = -2 then 'Holiday'
else sm.ShiftName
end as ShiftName,
case when sm2.ShiftId is null then 'Not assigned'
else Sm2.ShiftName
end as ShiftName2,
Sa.ShiftAllocationId
from ShiftAllocation as Sa
inner join EmployeeMaster as Em
on Sa.EmployeeId = Em.EmployeeId
left outer join ShiftMaster as Sm2
on Sa.ShiftId2 = Sm2.ShiftId
left outer join ShiftMaster as Sm
on Sa.ShiftId = Sm.ShiftId

Although I am not sure if it would be the best way to do it; you can try using CASE in your sql to arrive at a solution.
Edit : This http://www.dba-oracle.com/t_case_sql_clause.htm should help you if you want to try.

Related

How to calculate MAX not NULL in table?

How can I get that MAX 3 months with not NULL?
As result I need UserId, UserAgreementId and MAX Not NULL And Group BY UserId
month
Id
UserId
UserAgreementId
SubsriptionDate
Amount
1
NULL
NULL
NULL
NULL
NULL
2
12
222
33333
2020-02-02 00:00:00.000
40000
3
NULL
NULL
NULL
NULL
NULL
4
13
222
33333
2020-04-03 00:00:00.000
5000
5
NULL
NULL
NULL
NULL
NULL
6
15
222
33333
2020-06-04 00:00:00.000
7000
7
16
222
33333
2020-07-02 00:00:00.000
8000
8
17
222
33333
2020-08-09 00:00:00.000
4000
9
NULL
NULL
NULL
NULL
NULL
10
NULL
NULL
NULL
NULL
NULL
11
NULL
NULL
NULL
NULL
NULL
12
NULL
NULL
NULL
NULL
NULL
As Result must be smth like this
UserId
UserAgreementId
MAX
222
33333
3
Table AgreementId have SubsriptionDate in rows and I need to calculate period with max not empty Amount
UserAgreementId
SubsriptionDate
Amount
33333
2020-02-02 00:00:00.000
40000
33333
2020-04-03 00:00:00.000
5000
33333
2020-06-04 00:00:00.000
7000
33333
2020-07-02 00:00:00.000
8000
33333
2020-08-09 00:00:00.000
4000
What you're asking for is too complex for a query - it will take a long time to run.
For example, I've put together a draft below that just about gets the longest duration for each user, yet it references the same table 5 times.
This is barely readible, convuluted, and will tax the server more than you want.
Instead, fetch the records and process them in a more suitable programming language.
SELECT t.user_id, MAX(t.monthsTotal - s.monthsTotal + 1) AS longestDuration
FROM (SELECT a.*, YEAR(a.subscriptionDate) * 12 + a.month AS monthsTotal
FROM table_name) as t
INNER JOIN (SELECT a.*, YEAR(a.subscriptionDate) * 12 + a.month AS monthsTotal
FROM table_name AS a
LEFT OUTER JOIN table_name AS preceeding
ON a.user_id = preceeding.user_id
AND YEAR(a.subscriptionDate) * 12 + a.month = YEAR(preceeding.subscriptionDate) * 12 + preceeding.month + 1
WHERE preceedingMonth.id IS NULL) AS s
ON t.user_id = s.user_id
AND t.monthsTotal >= s.monthsTotal
LEFT OUTER JOIN (SELECT a.*, YEAR(a.subscriptionDate) * 12 + a.month AS monthsTotal
FROM table_name AS a
LEFT OUTER JOIN table_name AS preceeding
ON a.user_id = preceeding.user_id
AND YEAR(a.subscriptionDate) * 12 + a.month = YEAR(preceeding.subscriptionDate) * 12 + preceeding.month + 1
WHERE preceedingMonth.id IS NULL) AS dummy
ON t.user_id = dummy.user_id
AND dummy.monthsTotal > s.monthsTotal
AND t.monthsTotal > dummy.monthsTotal
WHERE dummy.id IS NULL
GROUP BY t.user_id

Full join in two columns with repeated values

I have two tables that look like this:
sMinMax:
PartNo baseID Min Max
11795 1 1 1
11795 5 0 0
11795 6 1 1
01655 65 2 3
vsStock:
PartNo baseID Qty
11795 1 1
11795 1 1
11795 55 1
I would like to join them so I get a table that shows all the columns together for all the parNo en bases like this:
result:
PartNo baseID Min Max Qty
11795 1 1 1 2
11795 5 0 0 null
11795 6 1 1 null
11795 55 null null 1
01655 65 2 3 null
So I would just do this with a full outer join on two columns but this gives the same results that I would expect from a left join. I tried 1000 things but this is my last try:
SELECT
a.sPart_ID
,a.uRALBase_ID
,a.MinQty
,a.MaxQty
,b.Qty
FROM [RALNHVTST].[dbo].[sMinMax] as a
FULL OUTER JOIN [RALNHVTST].[dbo].[vsStockList] as b
ON a.sPart_ID = b.sPart_ID
AND a.uRALBase_ID = b.uRALBase_ID
WHERE a.sPart_ID IS NOT NULL
AND a.sPart_ID = 1159
ORDER BY a.sPart_ID
but as I said this gives me the same results as a LEFT JOIN. Anyone have an idea what I'm doing wrong?
Something like that? This query gives me same result as you expected.
SELECT
CASE WHEN a.PartNo IS NOT NULL THEN a.PartNo ELSE b.PartNo END AS PartNo
,CASE WHEN a.baseId IS NOT NULL THEN a.baseId ELSE b.baseId END AS baseId
,a.[Min]
,a.[Max]
,SUM(b.Qty) AS Qty
FROM [dbo].[sMinMax] as a
FULL JOIN [dbo].[vsStock] as b
ON a.partNo = b.partNo
AND a.baseId = b.baseId
GROUP BY
CASE WHEN a.PartNo IS NOT NULL THEN a.PartNo ELSE b.PartNo END,
CASE WHEN a.baseId IS NOT NULL THEN a.baseId ELSE b.baseId END,
a.[Min],
a.[Max]
ORDER BY
CASE WHEN a.PartNo IS NOT NULL THEN a.PartNo ELSE b.PartNo END
Filtering in a full join is tricky. I would recommend filtering and aggregating in subqueries:
SELECT COALESCE(sm.sPart_ID, s.sPart_Id) as sPartId,
COALESCE(sm.uRALBase_ID, sm.uRALBase_ID
sm.MinQty, sm.MaxQty, s.Qty
FROM (SELECT sm.*
FROM [RALNHVTST].[dbo].[sMinMax] sm
WHERE sm.sPart_ID = 1159
) sm FULL OUTER JOIN
(SELECT s.sPart_ID, s.uRALBase_ID, SUM(qty) as qty
FROM [RALNHVTST].[dbo].[vsStockList] s
WHERE s.sPart_ID = 1159
GROUP BY s.sPart_ID, s.uRALBase_ID
) s
ON sm.sPart_ID = s.sPart_ID AND
sm.uRALBase_ID = s.uRALBase_ID
ORDER BY sPart_ID

combine two tables with sql

I have those given tables:
In table2 could be multiple rows for "Kost_ID", in output these "Kost_ID" should be only one row. "MW_ID" should be in result "MW"+ number (here "MW5" and "MW6" for "MW_ID" 5+6). Hope this is clear enough.
How could I do this with sql in an oracle db? thanks
Table1
ID Kost_ID Col1
2016 1 bla
2016 2 bla
2016 3 bla1
2016 4 abl
2016 5
2016 6
2016 7
2017 2
2017 3
Table2
ID Kost_ID MW_ID Euro
2016 1 1 10
2016 2 2 20
2016 3 6 30
2016 3 5 40
2016 5 5 50
2016 6 6 60
2016 7 3 70
2016 4 4 80
Result:
ID Kost_ID Col1 MW1 MW2 MW3 MW4 MW5 MW6
2016 1 bla 10
2016 2 bla 20
2016 3 bla1 40 30
2016 4 abl 80
2016 5 50
2016 6 60
2016 7 70
If you don't want to use Pivot Queries you can try with left joins, maybe a little boring, manual and old style
select t1.*,
t21.euro mw1,t22.euro mw2, t23.euro mw3,t24.euro mw4,t25.euro mw5,t26.euro mw6
from
table1 t1 left join table2 t21
on t1.id=t21.id
and t1.kost_id=t21.kost_id
and t21.mw_id=1
left join table2 t22
on t1.id=t22.id
and t1.kost_id=t22.kost_id
and t22.mw_id=2
left join table2 t23
on t1.id=t23.id
and t1.kost_id=t23.kost_id
and t23.mw_id=3
left join table2 t24
on t1.id=t24.id
and t1.kost_id=t24.kost_id
and t24.mw_id=4
left join table2 t25
on t1.id=t25.id
and t1.kost_id=t25.kost_id
and t25.mw_id=5
left join table2 t26
on t1.id=t26.id
and t1.kost_id=t26.kost_id
and t26.mw_id=6
order by t1.id, t1.kost_id
For completness pivot solution mentioned in comments:
select *
from table1 join table2 using (id, kost_id)
pivot (sum(euro) for mw_id in (1 mw1, 2 mw2, 3 mw3, 4 mw4, 5 mw5, 6 mw6))
order by id
Test example
(sorry for the delay)
i came close but it needs some improvement.
select a.ID, a.Kost_ID,a.Col1,
case b.MW_ID when 1 then b.Euro else null end MW1,
case b.MW_ID when 2 then b.Euro else null end MW2,
case b.MW_ID when 3 then b.Euro else null end MW3,
case b.MW_ID when 4 then b.Euro else null end MW4,
case b.MW_ID when 5 then b.Euro else null end MW5,
case b.MW_ID when 6 then b.Euro else null end MW6
from table1 a join table2 b
on (a.ID=b.ID and a.Kost_ID=b.Kost_ID )
ID Kost_ID Col1 MW1 MW2 MW3 MW4 MW5 MW6
2016 1 bla 10 NULL NULL NULL NULL NULL
2016 2 bla NULL 20 NULL NULL NULL NULL
2016 3 bla1 NULL NULL NULL NULL NULL 30
2016 3 bla1 NULL NULL NULL NULL 40 NULL
2016 4 abl NULL NULL NULL 80 NULL NULL
2016 5 NULL NULL NULL NULL NULL 50 NULL
2016 6 NULL NULL NULL NULL NULL NULL 60
2016 7 NULL NULL NULL 70 NULL NULL NULL

How to build query? Any idea?

3 tables:
Mark table:
student_id sa_id marks
1 1 75
1 2 80
1 3 100
2 4 85
2 5 90
2 6 60
course table:
course_code sat_id name_code
AAA 100 1 midterm1
AAA 100 2 midterm2
AAA 100 3 final
BBB 200 4 midterm1
BBB 200 5 midterm2
BBB 200 6 final
transform table:
sa_id sat_id
1 1
2 2
3 3
4 4
5 5
6 6
select course.course_code, mark.marks
from mark
left outer join transform on transform.sa_id = mark.sa_id
left outer join course on course.sat_id = transfrom.sat_id
where course.name_code = 'midterm1'
At the above query only midterm1 result, also we can extract mid2 and final
select mark.student_id,course.course_code, mark.marks, course.name_code
from mark
left outer join transform on transform.sa_id = mark.sa_id
left outer join course on course.sat_id = transfrom.sat_id
order by mark.student_id, course.course_code
Result will give:
student_id course_code marks name_code
1 AAA 100 75 midterm1
1 AAA 100 80 midterm2
1 AAA 100 100 final
2 BBB 200 85 midterm1
2 BBB 200 90 midterm2
2 BBB 200 60 final
So how to build query that should be
student_id course_code midterm1 midterm2 final
1 AAA 100 75 80 100
2 BBB 200 85 90 60
You can use case when , group by (and a fake aggregation function)
select
student_id
, course_code
, max(case when name_code ='midterm1' then mark else null) midterm1
, max(case when name_code ='midterm2' then mark else null) midterm2
, max(case when name_code ='final' then mark else null) final
from mark
left outer join transform on transform.sa_id = mark.sa_id
left outer join course on course.sat_id = transfrom.sat_id
group by student_id, course_code
order by mark.student_id, course.course_code
But if you don't like aggregation functio you can use a 3 seleft join on mark
select
mm1.student_id
, mm1.course_code
, mm1.mark midterm1
, mm2.mark midterm2
, mm3.mark finale
from mark as mm1
left join mark as mm2 on mm1.student_id = mm2.student_id and mm1.course_code = mm2.course_code
left join mark as mm3 on mm1.student_id = mm3.student_id and mm1.course_code = mm3.course_code
left outer join transform on transform.sa_id = mm1.sa_id
left outer join course on course.sat_id = transfrom.sat_id
where mm1.name_code = 'midterm1'
and mm2.name_code = 'midterm2'
and mm3.name_code = 'final'

Joining on optional

I have 2 tables:
Table1 - Criteria
Office_ID Bus_Stream Bus_Criteria Crit_Value
1 ABC 0 20
1 ABC 1 21
1 ABC 2 7
2 ABC 0 15
2 ABC 1 12
2 ABC 2 21
3 XYZ 1 17
3 XYZ 2 3
Table2 - Limit
Bus_Stream GroupID TypeID SubgroupID Bus_Limit
ABC 20 21 7 50
ABC 15 12 21 100
XYZ 99 17 3 120
I need to create a join that allows me to pull back:
Result
Bus_Stream Office_ID GroupID TypeID SubgroupID Bus_Limit
ABC 1 20 21 7 50
ABC 2 15 12 21 100
XYZ 3 (null) 17 3 120
Essentially, I need to join Table1.Crit_Value based on the following:
Table1.Bus_Criteria Table2
0 GroupID
1 TypeID
2 SubGroupID
with the added complication that if one or two of the 0/1/2 values from Bus_Criteria is missing, the joins will still occur on the remaining criteria.
I have tried a number of combinations of AND/OR on the join to no avail.
Any ideas folks?
This may be what you're after.. use a case statement on the join.
The problem here is your data in t2 isn't normalized, you could also unpivot the 3 data columns in t2 so the join is more natural.
SELECT T2.Bus_Stream, T1.Office_ID, T2.GroupID, T2.TypeID, T2.SubGroupId, T2.bus_Limit
FROM T1
INNER JOIN T2
on T1.Bus_Stream = T2.Bus_Stream
and T1.Crit_value = case when T1.Bus_Critiera = 0 then T2.GroupID
when T1.Bus_Critiera = 1 then T2.TypeID
when T1.Bus_Critiera = 2 then T2.SubGroupID
end
Did you try something like this?
SELECT
t1.*, t2.*
FROM Table1 t1
INNER JOIN Table2 t2 ON
t1.Bus_Stream = t2.Bus_Stream AND
CASE
WHEN t1.Bus_Criteria = 0
THEN t2.GroupID = t1.Crit_Value
WHEN t1.Bus_Criteria = 1
THEN t2.TypeID = t1.Crit_Value
ELSE
t2.SubGroupID = t1.Crit_Value
END