BD2: SQL _CASE with group by - sql

I have the following tables
---SALARY_ITEMS---
PERSONID | EMPLOYMENT _REF | GROUP1 | CODE | FROM | END | QUANTI
000101 XYX 400 11101 2020-02-12 2020-02-12 12
000101 XYX 300 1100 2020-01-29 2020-02-29 1
000102 XYY 450 11111 2020-02-01 2020-02-12 19
000102 XYY 400 11101 2020-02-02 2020-02-12 82
000103 XYA 500 1100 2020-02-10 2020-02-12 11
000104 XYB 700 1100 2020-01-12 2020-02-12 24
---PERSON ---
PERSONID NAME
000101 Carolina
000102 Helen
000103 Jack
000104 Anna
---EMPLOYMENT---
PERSONID EMPLOYMENT _REF POSITION
000101 XYX doctor
000102 XYY nurse
000103 XYA nurse
000104 XYB Proffesor
----absent---
PERSONID CODE2 FROM END
000101 123 2020-03-01 2020-06-30
000102 120 2020-02-05 2020-02-13
000102 123 2020-03-01 2020-03-28
000103 115 2020-05-05 2020-06-30
000104 123 2020-02-01 2020-05-30
What I tried to do: get all employee that they are doctor and nurse and have certain group with certain code and works over 100 hours in a 2020 -Feb.
The following SQL query give me what i want But i want to add something to my query that is :
create a new column to see if the employee was absent in the same period 2020-feb with absent code 120 or 119 or both.
If he was I will get the 'CODE2' ELSE 'NOTHING'.
How can I do this in DB2?
This is the result I need to get:
PERSONID | NAME | POSITION | QUANTITY |ABSENT (this what i want to have)
000102 Helen NURSE 101 120
Query:
SELECT
S.PERSONID, P.NAME,E.POSTION , sum(S.QUANTITY) as QUANTITY
FROM
SALARY_ITEMS S
LEFT JOIN
PERSON P ON S.PERSONID = P.PERSONID
LEFT JOIN
EMPLOYMENT E ON E.EMPLOYMENT_REF = S.EMPLOYMENT _REF
WHERE
S.group1 IN ('400', '440', '450', '470', '640')
AND S.code IN ('11101', '11111', '11121', '11131', '11141')
AND S.from >= '2020-02-01'
AND S.end <= '2020-02-29'
AND E.POSTION IN ('nurse', 'doctor')
AND (SELECT SUM(S2.QUANTITY) AS QUANTITY2
FROM SALARY_ITEMS S2
WHERE S2.group1 IN ('400', '440', '450', '470', '640')
AND S2.code IN ('11101', '11111', '11121', '11131', '11141')
AND S2.from >= '2020-02-01'
AND S2.end <= '2020-02-29'
AND S.PERSONID = S2.PERSONID) >= '100'
GROUP BY
S.PERSONID, P.NAME, E.POSTION

Related

I have 3 tables Flight_schedule, Flights and third is Route I need a stored procedure in SQL which give the cheapest flight on a given date

I have 3 tables Flight_schedule, Flights and third is Route I need a stored procedure in SQL which give the cheapest flight on a given date.
When the parameter date is passed to procedure suppose 2 February so the result would be the lowest fare flight on the 2 Feb.
Here is the code where I have joined the tables and passed the parameter to stored procedure but when I am confused in the condition part.
Create proc spCheapestFlight
#FLIGHT_DATE DATE
AS
BEGIN
SELECT Flight_schedule.FlightDate,Flight_schedule.Departure,route.source, route.destination,
Flight_schedule.Arrival
,Flight_schedule.Fare,Flights.Flight_name
FROM Flight_schedule
inner join route ON Flight_schedule.Route_id=route.Route_id inner join
Flights on Flights.Flight_id=Flight_schedule.Flight_id
where Flight_schedule.FlightDate = #FLIGHT_DATE
END
Flight_schedule
F_Id
Flight_id
Total_Fare
FlightDate
Departure
Arrival
Route_Id
Fare
10000
1
1001
2022-02-01
09:30:30.0000000
11:20:45.0000000
100
7500.8
10001
2
1002
2022-02-02
09:45:30.0000000
11:55:45.0000000
101
7000.9
10002
3
1003
2022-02-03
10:30:30.0000000
12:20:45.0000000
102
5111.5
10003
4
1004
2022-02-04
11:30:30.0000000
14:20:45.0000000
103
5500.9
10004
5
1005
2022-02-05
12:30:30.0000000
15:20:45.0000000
104
9000.7
10005
1
1006
2022-02-06
13:30:30.0000000
16:20:45.0000000
105
8675.5
10006
2
1007
2022-02-07
14:30:30.0000000
17:20:45.0000000
106
4000.5
10007
3
1008
2022-02-08
15:30:30.0000000
18:20:45.0000000
107
4100.5
10008
4
1009
2022-02-09
16:30:30.0000000
19:20:45.0000000
101
4000.3
10009
2
1006
2022-02-10
06:30:30.0000000
08:20:45.0000000
108
4000.3
Flights
Flight_id
Flight_name
Capacity
1
Vistara
30
2
Indigo
30
3
SpiceJet
30
4
Go_First
30
5
Air India
30
Route
route_id
source
destination
100
Mumbai
Delhi
101
Delhi
Ahmedabad
102
Ahmedabad
Delhi
103
Ahmedabad
Mumbai
104
Chennai
Mumbai
105
Chennai
Goa
106
Chennai
Delhi
107
Goa
Delhi
108
Bangalore
Delhi
109
Hyderabad
Delhi
your data does not show more than 1 flight per day, in addition there is no need for table Flights and table Route to get result, you should join table FlightSchedule with itself in order to get the minimum fare. your problem can be solve with table-value function(TVF). you should change you PROCEDURE as follows:
CREATE PROCEDURE spCheapest_Costliest_Flight (#FlightDate DATE)
AS
SELECT FS.FlightDate,FS.Departure,route.source, route.destination,
FS.Arrival ,T.Fare,Flights.Flight_name
FROM Flight_schedule FS
inner join route ON FS.Route_id=route.Route_id
inner join Flights on Flights.Flight_id=FS.Flight_id
inner join (select FlightDate FlightDate,MIN(Fare) Fare
from Flight_schedule GROUP BY FlightDate) T
ON T.FlightDate=FS.FlightDate and T.FlightDate=#FlightDate and FS.FlightDate=#FlightDate
GO

Query to find active days per year to find revenue per user per year

I have 2 dimension tables and 1 fact table as follows:
user_dim
user_id
user_name
user_joining_date
1
Steve
2013-01-04
2
Adam
2012-11-01
3
John
2013-05-05
4
Tony
2012-01-01
5
Dan
2010-01-01
6
Alex
2019-01-01
7
Kim
2019-01-01
bundle_dim
bundle_id
bundle_name
bundle_type
bundle_cost_per_day
101
movies and TV
prime
5.5
102
TV and sports
prime
6.5
103
Cooking
prime
7
104
Sports and news
prime
5
105
kids movie
extra
2
106
kids educative
extra
3.5
107
spanish news
extra
2.5
108
Spanish TV and sports
extra
3.5
109
Travel
extra
2
plans_fact
user_id
bundle_id
bundle_start_date
bundle_end_date
1
101
2019-10-10
2020-10-10
2
107
2020-01-15
(null)
2
106
2020-01-15
2020-12-31
2
101
2020-01-15
(null)
2
103
2020-01-15
2020-02-15
1
101
2020-10-11
(null)
1
107
2019-10-10
2020-10-10
1
105
2019-10-10
2020-10-10
4
101
2021-01-01
2021-02-01
3
104
2020-02-17
2020-03-17
2
108
2020-01-15
(null)
4
102
2021-01-01
(null)
4
103
2021-01-01
(null)
4
108
2021-01-01
(null)
5
103
2020-01-15
(null)
5
101
2020-01-15
2020-02-15
6
101
2021-01-01
2021-01-17
6
101
2021-01-20
(null)
6
108
2021-01-01
(null)
7
104
2020-02-17
(null)
7
103
2020-01-17
2020-01-18
1
102
2020-12-11
(null)
2
106
2021-01-01
(null)
7
107
2020-01-15
(null)
note: NULL bundle_end_date refers to active subscription.
user active days can be calculated as: bundle_end_date - bundle_start_date (for the given bundle)
total revenue per user could be calculated as : total no. of active days * bundle rate per day
I am looking to write a query to find revenue generated per user per year.
Here is what I have for the overall revenue per user:
select pf.user_id
, sum(datediff(day, pf.bundle_start_date, coalesce(pf.bundle_end_date, getdate())) * bd.price_per_day) total_cost_per_bundle
from plans_fact pf
inner join bundle_dim bd on bd.bundle_id = pf.bundle_id
group by pf.user_id
order by pf.user_id;
You need a 'year' table to help parse out each multi-year spanning row into it's seperate years. For each year, you need to also recalculate the start and end dates. That's what I do in the yearParsed cte in the code below. I hard code the years into the join statement that creates y. You probably will do it different but however you get those values will work.
After that, pretty much sum as you did before, just adding the year column to your grouping.
Aside from that, all I did was move the null coalesce logic to the cte to make the overall logic simpler.
with yearParsed as (
select pf.*,
y.year,
startDt = iif(pf.bundle_start_date > y.startDt, pf.bundle_start_date, y.startDt),
endDt = iif(ap.bundle_end_date < y.endDt, ap.bundle_end_date, y.endDt)
from plans_fact pf
cross apply (select bundle_end_date = isnull(pf.bundle_end_date, getdate())) ap
join (values
(2019, '2019-01-01', '2019-12-31'),
(2020, '2020-01-01', '2020-12-31'),
(2021, '2021-01-01', '2021-12-31')
) y (year, startDt, endDt)
on pf.bundle_start_date <= y.endDt
and ap.bundle_end_date >= y.startDt
)
select yp.user_id,
yp.year,
total_cost_per_bundle = sum(datediff(day, yp.startDt, yp.endDt) * bd.bundle_cost_per_day)
from yearParsed yp
join bundle_dim bd on bd.bundle_id = yp.bundle_id
group by yp.user_id,
yp.year
order by yp.user_id,
yp.year;
Now, if this is common, you should probably create a base-table for your 'year' table. But if it's not common, but for this report you don't want to have to keep coming back to hard-code the year information into the y table, you can do this:
declare #yearTable table (
year int,
startDt char(10),
endDt char(10)
);
with y as (
select year = year(min(pf.bundle_start_date))
from #plans_fact pf
union all
select year + 1
from y
where year < year(getdate())
)
insert #yearTable
select year,
startDt = convert(char(4),year) + '-01-01',
endDt = convert(char(4),year) + '-12-31'
from y;
and it will create the appropriate years for you. But you can see why creating a base table may be preferred if you have this or a similar need often.

SQL Query to extract Average Quantity

I want to calculate the average quantity customer purchases in one basket
(Where 1 Basket = Multitple purchases in 1 day)
from the table transaction and update it into cust360.average_basket_Qty
Transactions:-
Trasactions_ID cust_id Tran_date Qty Total_amt
80712190438 270351 2014-02-28 00:00:00.000 5 4265.3
29258453508 270384 2014-02-27 00:00:00.000 5 8270.925
51750724947 273420 2014-02-24 00:00:00.000 2 1748.11
93274880719 271509 2014-02-24 00:00:00.000 3 4518.345
51750724947 273420 2014-02-23 00:00:00.000 2 1748.11
97439039119 272357 2014-02-23 00:00:00.000 2 1821.04
45649838090 273667 2014-02-22 00:00:00.000 1 1602.25
Cust360 Table: -
Cust_id Gender Age Basket_count Total_sale Date Average_basket_Qty
266783 M 525 0 3113 2013-02-20 NULL
266784 F 314 1 5694 2012-12-04 NULL
266785 F 392 0 21613 2013-08-01 NULL
266788 F 551 0 6092 2013-02-12 NULL
266794 F 564 1 27981 2014-02-12 NULL
Following query should work for you
UPDATE DEST
SET DEST.Average_basket_Qty = SRC.AVG_QTY
FROM Cust360 DEST
INNER JOIN
(
SELECT CUST_ID, CAST(TRAN_DATE AS DATE), AVG(QTY) AVG_QTY
FROM Transactions
GROUP BY CUST_ID,CAST(TRAN_DATE AS DATE)
) SRC ON SRC.CUST_ID=DEST.Cust_id

Stored Procedure Select from 3 tables

I have three tables in my database Sales, SalesPeople and Appliances.
Sales
SaleDate EmployeeID AppID Qty
---------- ---------- ----- -----------
2010-01-01 1412 150 1
2010-01-05 3231 110 1
2010-01-03 2920 110 2
2010-01-13 1412 100 1
2010-01-25 1235 150 2
2010-01-22 1235 100 2
2010-01-12 2920 150 3
2010-01-14 3231 100 1
2010-01-15 1235 300 1
2010-01-03 2920 200 2
2010-01-31 2920 310 1
2010-01-05 1412 420 1
2010-01-15 3231 400 2
SalesPeople
EmployeeID EmployeeName CommRate BaseSalary SupervisorID
---------- ------------------------------ ----------- ----------- ------------
1235 Linda Smith 15 1200 1412
1412 Anne Green 12 1800 NULL
2920 Charles Brown 10 1150 1412
3231 Harry Purple 18 1700 1412
Appliances
ID AppType StoreID Cost Price
---- -------------------- ------- ------------- -------------
100 Refrigerator 22 150 250
110 Refrigerator 20 175 300
150 Television 27 225 340
200 Microwave Oven 22 120 180
300 Washer 27 200 325
310 Washer 22 280 400
400 Dryer 20 150 220
420 Dryer 22 240 360
How can I obtain this result? (That displays the profitability of each of the salespeople ordered from the most profitable to the least. Gross is simply the sum of the quantity of items sold multiplied by the price. Commission is calculated from the gross minus the cost of those items (i.e. from
qty*(price-cost)). Net profit is the total profit minus commission.)
Name Gross Commission Net Profit
------------- ----- ---------- ---------
Charles Brown 2380 83.5 751.5
Linda Smith 1505 83.25 471.75
Harry Purple 990 65.7 299.3
Anne Green 950 40.2 294.8
My attempt:
CREATE PROC Profitability AS
SELECT
sp.EmployeeName, (sum(s.Qty) * a.Price) as [Gross],
[Gross] - a.Cost, as [Commision],
SOMETHING as [Net Profit]
FROM
Salespeople sp, Appliances a, Sales s
WHERE
s.AppID = a.ID
AND sp.EmployeeID = s.EmployeeID
GROUP BY
sp.EmployeeName
GO
EXEC Profitability
Simple rule: Never use commas in the FROM clause. Always use explicit JOIN syntax.
In addition to fixing the JOIN syntax, your query needs a few other enhancements for the aggregation functions:
SELECT sp.EmployeeName, sum(s.Qty * a.Price) as Gross,
SUM(s.Qty * (a.Price - a.Cost)) * sp.CommRate / 100.0 as Commission,
SUM(s.Qty * (a.Price - a.Cost)) * (1 - sp.CommRate / 100.0) as NetProfit
FROM Sales s JOIN
Salespeople sp
ON sp.EmployeeID = s.EmployeeID JOIN
Appliances a
ON s.AppID = a.ID
GROUP BY sp.EmployeeName sp.CommRate
ORDER BY NetProfit DESC;

Merge two tables using common fields

I have two tables, which I need to get data from table 1 to table 2 by matching customer name & Sale date. In the first table, the name is in two columns but the other table its in one column.
> list(CustomerSales.CSV)
[[1]]
CustomerFirstName CustomerLastName SaleDate_Time InvoiceNo InvoiceValue
1 Hendricks Eric 30-09-2015 13:00 10 5000
2 Fier Marilyn 02-10-2015 15:30 15 18000
3 O'Brien Donna 03-10-2015 13:30 16 25000
4 Perez Barney 03-10-2015 16:10 17 20000
5 Fier Marilyn 04-10-2015 11:10 18 6000
6 Hendricks Eric 05-10-2015 14:00 19 8000
> list(ReturnSales.CSV)
[[1]]
CustomerName SaleDate_Time ReturnDate_Time ReturnNo ReturnValue
1 Hendricks Eric 05-10-2015 14:00 10-10-2015 14:00 1 1000
2 O'Brien Donna 03-10-2015 13:30 15-10-2015 13:30 2 2000
3 Perez Barney 03-10-2015 16:10 12-10-2015 16:10 3 1500
4 Fier Marilyn 02-10-2015 15:30 08-10-2015 15:30 4 2000
The result should be a table like this.
list(ReturnSales.CSV)
[[1]]
CustomerName SaleDate_Time InvoiceNo InvoiceValue ReturnDate_Time ReturnNo ReturnValue
1 Hendricks Eric 05-10-2015 14:00 19 8000 10-10-2015 14:00 1 1000
2 O'Brien Donna 03-10-2015 13:30 16 25000 15-10-2015 13:30 2 2000
3 Perez Barney 03-10-2015 16:10 17 20000 12-10-2015 16:10 3 1500
4 Fier Marilyn 02-10-2015 15:30 15 18000 08-10-2015 15:30 4 2000
Table 2 customer name & SaleDate_Time should be match with table 1 CustomerFirstName, CustomerLastName, & SaleDate_Time. Then combine from table 1, InvoiceNo & InvoiceValue to table 2.
Any suggestions?
Are you looking for SQL Query for the above scenario then you can something like below.
SELECT RS.CustomerName
,CS.SaleDate_Time
,CS.InvoiceNo
,CS.InvoiceValue
,RS.Return_DateTime
,RS.ReturnNo
,RS.ReturnValue
FROM CustomerSales CS
INNER JOIN ReturnSales RS
ON RS.CustomerName = CS.CustomerfirstName + ' ' + Cs.CustomerLastName
WHERE RS.SaleDate_Time = CS.SaleDate_Time