Highest occupant with his details using view & max? - sql

Query to get the house details of the house having the highest occupancy
There are two tables houses & tenant histories used to calculate the highest occupancy.
So first I'm using datediff function to get the duration of stay.
then I create view so that it act as a virtual table & I can access the column to get max value.
create view [dbo].[vWHouseStay]
as
select profile_id,
house_Id,
house_type,
bhk_details,Bed_type,
bed_count,
furnishing_type ,
DATEDIFF(MONTH,move_in_date,move_out_date) AS 'Total Length of stay'
from Tenancy_histories
join houses on tenancy_histories.house_Id = houses.house_id
What I need is highest occupant with house details. How do I do that? Basically it should just return one house with max [Total Length of stay].
table structure:
**Tenancy_histories**
Field Type Null Key Default
id int(11) NO PRI auto_increment
profile_id int(11) NO FK
house_id int(11) NO FK
move_in_date date NO
move_out_date date YES
rent int(11) NO
Bed_type varchar(255) YES
move_out_reason varchar(255) YES
**Houses**
Field Type Null Key Default
house_id int(11) NO PRI auto_increment
house_type varchar(255) YES
bhk_details varchar(255) YES
bed_count int(11) NO
furnishing_type varchar(255) YES
Beds_vacant int(11) NO
sample data
house_id house_type bhk_details bed_count furnishing_type OccupancyDays
5 Independent 4 BHK 4 fully-furnished 443
7 Apartment 3 BHK 3 semifurnished 417
4 Apartment 2 BHK 2 fully-furnished 397
18 Independent 2 BHK 2 fully-furnished 358
16 Apartment 3 BHK 3 fully-furnished 324
19 Independent 3 BHK 3 fully-furnished 290
3 Apartment 3 BHK 6 fully-furnished 226
1 Apartment 3 BHK 5 unfurnished NULL
2 Apartment 3 BHK 3 unfurnished NULL
17 Independent 3 BHK 3 fully-furnished NULL
6 Apartment 3 BHK 3 semifurnished NULL
8 Apartment 2 BHK 4 fully-furnished NULL
sample data [tenancy histories]
id profile_id house_id move_in_date move_out_date rent Bed_type move_out_reason
242 1 5 2015-02-12 2016-04-30 7500 bed MOVE_OUT
243 2 2 2015-06-05 NULL 11000 room
244 3 4 2015-10-28 2016-11-28 12000 room RENT_CHANGE
245 4 1 2015-04-26 NULL 8000 bed
246 5 3 2015-05-15 2015-12-27 9000 bed MOVE_OUT
247 6 8 2015-12-25 NULL 10200 room
248 7 6 2015-11-20 NULL 6500 bed
249 8 7 2015-11-10 2016-12-31 7200 bed MOVE_OUT
250 9 9 2015-10-15 NULL 7500 bed
251 10 10 2015-06-20 NULL 7500 bed
252 11 19 2015-08-29 2016-06-14 8000 bed INTERNAL_TRANSFER
253 12 15 2015-02-24 NULL 11000 room
254 13 12 2015-02-25 NULL 12000 room
255 14 18 2016-01-07 2016-12-30 13500 room MOVE_OUT
256 15 13 2015-04-07 NULL 6500 bed
257 16 17 2015-04-23 NULL 6500 bed
258 17 14 2015-02-10 NULL 10500 room
259 18 16 2015-10-16 2016-09-04 8000 bed MOVE_OUT
260 19 20 2015-09-26 NULL 7500 bed
261 20 11 2015-09-30 NULL 9500 bed

Looks like you want to aggregate over all tenancy history. Here would be how. This can be used in a view as well.
;with cte as(
select
h.house_id
,h.house_type
,h.bhk_details
,h.bed_count
,h.furninshing_type
,OccupancyDays = sum(datediff(day,th.move_in_date,move_out_date))
from
Houses h
inner join
Tenancy_histories th on th.house_id = h.house_id)
group by
h.house_id
,h.house_type
,h.bhk_details
,h.bed_count
,h.furninshing_type
select TOP 1 --you can remove the TOP 1 to bring them all back
*
from cte
order by OccupancyDays desc

Related

Count number of unique occurrences of a key value corresponding to each ID column

I have a table in DB2 as below :
Key ID SubID
Abc123 576 10
Abc123 576 12
Abc124 576 13
Abc125 577 14
Abc126 578 15
Abc127 578 16
Abc128 578 17
Want to create a additional count column where it counts number of unique occurrences of key value for each ID and the output should be as below
Key ID SubID Count
Abc123 576 10 2
Abc123 576 12 2
Abc124 576 13 2
Abc125 577 14 1
Abc126 578 15 3
Abc127 578 16 3
Abc128 578 17 3
I tried below
select Key, ID, SubId ,
count(Key) over (partition by Key) as count
from table
Appreciate any help!
You cannot use a window function with the DISTINCT qualifier. You can use a scalar subquery to count the rows you want.
For example:
select *,
(select count(distinct key) from t x where x.id = t.id) as cnt
from t
Result:
KEY ID SUBID CNT
------- ---- ------ ---
Abc123 576 10 2
Abc123 576 12 2
Abc124 576 13 2
Abc125 577 14 1
Abc126 578 15 3
Abc127 578 16 3
Abc128 578 17 3
See running example at db<>fiddle.

looking for values from another table where they do not exist in a given group

I have two tables:
SHOPPING
date
id_customer
id_shop
id_fruit
28.03.2018
7423
123
1
13.02.2019
8408
354
1
28.03.2019
7767
123
9
13.02.2020
8543
472
7
28.03.2020
8640
346
9
13.02.2021
7375
323
9
28.03.2021
7474
323
8
13.02.2022
7476
499
1
28.03.2022
7299
123
4
13.02.2023
8879
281
2
28.03.2023
8353
452
1
13.02.2024
8608
499
6
28.03.2024
8867
318
1
13.02.2025
7997
499
6
28.03.2025
7715
499
4
13.02.2026
7673
441
7
FRUITS
id_fruit
name
1
apple
2
pear
3
grape
4
banana
5
plum
6
melon
7
watermelon
8
orange
9
pineapple
I would like to find fruits that have never been bought in a specific id_shop
I tried with this:
SELECT
s.idshop,
s.id_fruit ,
f.name
FROM
shopping s
LEFT JOIN fruit f ON f.id_fruit = s.id_fruit
WHERE NOT EXISTS (
SELECT *
FROM
fruit f1
WHERE f1.id_fruit = s.id_fruit
)
but it does not work...
Yes, you need an OUTER JOIN, but that should be RIGHT JOIN along with NULL values picked from shopping table after join applied, considering your current query such as
SELECT f.*
FROM shopping s
RIGHT JOIN fruit f
ON f.id_fruit = s.id_fruit
WHERE s.id_fruit IS NULL
Demo

Redshift SQL query help needed

Table order_details:
order_id dish_id category_id
----------------------------------
601 22 123
601 23 234
603 32 456
603 54 456
603 11 543
603 19 456
From the sample table provided above: how can I group the order_id,dish_id and category_id on the basis of distinct group with respect to each order_id?
The result should look like
order_id dish_id category_id count
---------------------------------------------
601 22 123 1
601 23 234 1
603 32 456 3
603 54 452 3
603 11 543 3
603 19 456 3
Note:
Like dish_id 22 in order_id 601 went along with 1 different distinct category_id i.e 234, and similarly in order_id 603 dish_id 32 went along 2 different distinct category_id ie 456, 543
If I assume that the triplets are unique, you seem to want 1 less than the count of the group. That would be:
select t.*,
(count(*) over (partition by order_id) - 1) as cnt
from t;

Update or Select into ORACLE

I am using the following statement;
SELECT RESV_ID, BOOKING_CUS_ID, ACC_ID,
(SELECT F.FLI_PRICE FROM FLIGHT F WHERE F.FLI_ID = R.IN_FLIGHT_ID) AS DEPART_FLIGHT_PRICE,
(SELECT F1.FLI_PRICE FROM FLIGHT F1 WHERE F1.FLI_ID = R.OUT_FLIGHT_ID) AS RETURN_FLIGHT_PRICE,
(SELECT AC.ACC_PRICEPN FROM ACCOMMODATION AC WHERE AC.ACC_ID = R.ACC_ID) AS ACCOMMODATION_PRICE
FROM HOLIDAY_RESERVATION R;
to yield the following results;
RESV_ID BOOKING_CUS_ID ACC_ID DEPART_FLIGHT_PRICE RETURN_FLIGHT_PRICE ACCOMMODATION_PRICE
---------- -------------- ---------- ------------------- ------------------- -------------------
1 1 2 520 450 350
2 3 4 250 150 150
3 5 6 290 300 450
4 7 7 399 450 650
5 9 365 345
6 11 558 460
7 13 250 250
8 15 550 550
9 17 25 250
10 19 19 450
10 rows selected.
Question:
How do I sum up the price fields, SOME PRICES ARE NOT AVAILABLE because a reservation was either made for accommodation only or flight only, hence both values will not be present always and this is where the issue lies
DEPART_FLIGHT_PRICE RETURN_FLIGHT_PRICE ACCOMMODATION_PRICE
Furthermore:
I wish to insert or update the SUM of those three values into a SUBTOTAL in the reservation table, perhaps by using select into or update, I have spent a whole day trying to do this but my skills are limited. any help will be greatly appreciated.
Flight table
FLI_ID FLI_CO FLI_AIRCRA DEPT_AIRPORT ARRV_AIRPORT DEPT_TIME ARRV_TIME FLI_PRICE
1 BD425 Boeing 707 1 12 18-MAR-12 02.24.00 AM 18-MAR-12 06.24.00 AM 520
2 LX345 Beriev 30 6 7 20-MAR-12 03.30.00 PM 20-MAR-12 04.20.00 PM 250
3 NZ4445 Boeing 720 9 14 25-MAR-12 09.00.00 AM 25-MAR-12 05.00.00 PM 290
4 TP351 Boeing 767 10 15 25-MAR-12 11.25.00 AM 25-MAR-12 03.35.00 PM 399
5 BA472 Boeing 720 5 14 26-MAR-12 01.05.00 PM 26-MAR-12 04.15.00 PM 365
Accommodation
ACC_ID ACC_TYPE_CODE ACC_DESC ACC_PRICEPN ACC_ROOMS RESORT_ID ACC_ADDR CITY_ID
1 1 Three bedroom bungalow near theme park 500 3 1
2 1 Two bedroom bungalow next to disney house 350 2 1
3 1 One bedroom bungalow with lake view 250 2 2
4 2 One bedroom chalet near the lake 150 1 2
5 2 Four bedroom chalet near the tree house 600 4 3
Reservation
RESV_ID EMP_ID BOOKING_CUS_ID RESV_DATE HOLIDAY_S HOLIDAY_E IN_FLIGHT_ID OUT_FLIGHT_ID IN_FLIGHT_SEATS_NO OUT_FLIGHT_SEATS_NO ACC_ID SUBTOTAL
1 338 1 16-FEB-12 18-MAR-12 20-APR-12 1 11 2 2 2
2 335 3 10-JAN-12 20-MAR-12 22-APR-12 2 12 2 2 4
3 338 5 05-MAR-12 25-MAR-12 26-APR-12 3 13 2 2 6
4 328 7 02-JAN-12 25-MAR-12 25-APR-12 4 14 2 2 7
5 311 9 20-JAN-12 26-MAR-12 21-APR-12 5 15 2 2
6 317 11 07-JAN-12 27-MAR-12 22-APR-12 6 16 2 2
7 344 13 29-FEB-12 15-MAR-12 12-APR-12 7 17 2 2
8 326 15 11-JAN-12 18-MAR-12 12-APR-14 8 18 2 2
9 329 17 16-JAN-12 19-MAR-12 17-APR-12 25
10 323 19 18-FEB-12 20-MAR-12 21-APR-12 19
Okay I managed to yield the results that i wanted
SELECT HR.RESV_ID, F_IN.FLI_ID, F_IN.FLI_PRICE, F_OUT.FLI_ID, F_OUT.FLI_PRICE, AC.ACC_ID, AC.ACC_PRICEPN, NVL(F_IN.FLI_PRICE,0)+NVL(F_OUT.FLI_PRICE,0)+NVL(AC.ACC_PRICEPN,0) AS TOTAL
FROM HOLIDAY_RESERVATION HR
LEFT JOIN FLIGHT F_IN ON HR.IN_FLIGHT_ID = F_IN.FLI_ID
LEFT JOIN FLIGHT F_OUT ON HR.OUT_FLIGHT_ID = F_OUT.FLI_ID
LEFT JOIN ACCOMMODATION AC ON HR.ACC_ID = AC.ACC_ID
ORDER BY HR.RESV_ID;
YIELDS
RESV_ID FLI_ID FLI_PRICE FLI_ID FLI_PRICE ACC_ID ACC_PRICEPN TOTAL
---------- ---------- ---------- ---------- ---------- ---------- ----------- ----------
1 1 500 11 555 2 350 1405
2 2 150 12 253 4 150 553
3 3 300 13 345 6 450 1095
4 4 450 14 343 7 650 1443
5 5 345 15 242 587
6 6 460 16 460 920
7 7 250 17 250 500
8 8 550 18 550 1100
9 25 250 250
10 19 450 450
And the following statement is to update the reservation table.
Thanks to Leigh Riffel from DBA stackxchange for the following code
UPDATE HOLIDAY_RESERVATION R SET SUBTOTAL =
NVL((SELECT F.FLI_PRICE FROM FLIGHT F WHERE F.FLI_ID = R.IN_FLIGHT_ID), 0) +
NVL((SELECT F.FLI_PRICE FROM FLIGHT F WHERE F.FLI_ID = R.OUT_FLIGHT_ID), 0) +
NVL((SELECT AC.ACC_PRICEPN FROM ACCOMMODATION AC WHERE AC.ACC_ID = R.ACC_ID), 0);
Now the subtotal is populated with the values obtained from the sum performed above >>
RESV_ID EMP_ID BOOKING_CUS_ID RESV_DATE HOLIDAY_S HOLIDAY_E IN_FLIGHT_ID OUT_FLIGHT_ID IN_FLIGHT_SEATS_NO OUT_FLIGHT_SEATS_NO ACC_ID SUBTOTAL
---------- ---------- -------------- --------- --------- --------- ------------ ------------- ------------------ ------------------- ---------- ----------
1 338 1 16-FEB-12 18-MAR-12 20-APR-12 1 11 2 2 2 1405
2 335 3 10-JAN-12 20-MAR-12 22-APR-12 2 12 2 2 4 553
3 338 5 05-MAR-12 25-MAR-12 26-APR-12 3 13 2 2 6 1095
4 328 7 02-JAN-12 25-MAR-12 25-APR-12 4 14 2 2 7 1443
5 311 9 20-JAN-12 26-MAR-12 21-APR-12 5 15 2 2 587
6 317 11 07-JAN-12 27-MAR-12 22-APR-12 6 16 2 2 920
7 344 13 29-FEB-12 15-MAR-12 12-APR-12 7 17 2 2 500
8 326 15 11-JAN-12 18-MAR-12 12-APR-14 8 18 2 2 1100
9 329 17 16-JAN-12 19-MAR-12 17-APR-12 25 250
10 323 19 18-FEB-12 20-MAR-12 21-APR-12 19 450
Subsequently the code was added to a trigger (which was the original intention)
CREATE OR REPLACE TRIGGER HR_SUBTOTAL
BEFORE INSERT OR UPDATE ON HOLIDAY_RESERVATION
FOR EACH ROW
BEGIN
SELECT
NVL((SELECT F.Fli_Price FROM Flight F WHERE F.Fli_ID = :new.In_Flight_ID), 0) +
NVL((SELECT F.Fli_Price FROM Flight F WHERE F.Fli_ID = :new.Out_Flight_ID), 0) +
NVL((SELECT AC.Acc_PricePn FROM Accomodation AC WHERE AC.Acc_ID = :new.Acc_ID), 0)
INTO :new.Subtotal
FROM dual;
END;
/
For the SUM, assuming you want to treat NULL values as 0, you'd just need to do an NVL on the numbers
NVL( DEPART_FLIGHT_PRICE, 0 ) +
NVL( RETURN_FLIGHT_PRICE, 0 ) +
NVL( ACCOMMODATION_PRICE, 0 )
As for the UPDATE, it sounds like you just need a correlated UPDATE statement.
UPDATE reservation r
SET subtotal = (SELECT (SELECT NVL( DEPART_FLIGHT_PRICE, 0 ) +
NVL( RETURN_FLIGHT_PRICE, 0 ) +
NVL( ACCOMMODATION_PRICE, 0 )
FROM (SELECT RESV_ID,
BOOKING_CUS_ID,
ACC_ID,
(SELECT F.FLI_PRICE
FROM FLIGHT F
WHERE F.FLI_ID = R.IN_FLIGHT_ID) AS DEPART_FLIGHT_PRICE,
(SELECT F1.FLI_PRICE
FROM FLIGHT F1
WHERE F1.FLI_ID = R.OUT_FLIGHT_ID) AS RETURN_FLIGHT_PRICE,
(SELECT AC.ACC_PRICEPN
FROM ACCOMMODATION AC
WHERE AC.ACC_ID = R.ACC_ID) AS ACCOMMODATION_PRICE
FROM dual));
You are asking:
How do I sum up the price fields, as you can see some of them can have nulls.
DEPART_FLIGHT_PRICE RETURN_FLIGHT_PRICE ACCOMMODATION_PRICE
Just enclose them in NVL function as follows:
NVL(DEPART_FLIGHT_PRICE, 0)
and then sum them up.
For the second part, what you need is a MERGE statement. A good example is at http://www.oracle-developer.net/display.php?id=203

SQL query self join

I am working on a query for a report in Oracle 10g.
I need to generate a short list of each course along with the number of times they were offered in the past year (including ones that weren't actually offered).
I created one query
SELECT coursenumber, count(datestart) AS Offered
FROM class
WHERE datestart BETWEEN (sysdate-365) AND sysdate
GROUP BY coursenumber;
Which produces
COURSENUMBER OFFERED
---- ----------
ST03 2
PD01 1
AY03 2
TB01 4
This query is all correct. However ideally I want it to list those along with COURSENUMBER HY and CS in the left column as well with 0 or null as the OFFERED value. I have a feeling this involves a join of sorts, but so far what I have tried doesn't produce the classes with nothing offered.
The table normally looks like
REFERENCE_NO DATESTART TIME TIME EID ROOMID COURSENUMBER
------------ --------- ---- ---- ---------- ---------- ----
256 03-MAR-11 0930 1100 2 2 PD01
257 03-MAY-11 0930 1100 12 7 PD01
258 18-MAY-11 1230 0100 12 7 PD01
259 24-OCT-11 1930 2015 6 2 CS01
260 17-JUN-11 1130 1300 6 4 CS01
261 25-MAY-11 1900 2000 13 6 HY01
262 25-MAY-11 1900 2000 13 6 HY01
263 04-APR-11 0930 1100 13 5 ST03
264 13-SEP-11 1930 2100 6 4 ST03
265 05-NOV-11 1930 2100 6 5 ST03
266 04-FEB-11 1430 1600 6 5 ST03
267 02-JAN-11 0630 0700 13 1 TB01
268 01-FEB-11 0630 0700 13 1 TB01
269 01-MAR-11 0630 0700 13 1 TB01
270 01-APR-11 0630 0700 13 1 TB01
271 01-MAY-11 0630 0700 13 1 TB01
272 14-MAR-11 0830 0915 4 3 AY03
273 19-APR-11 0930 1015 4 3 AY03
274 17-JUN-11 0830 0915 14 3 AY03
275 14-AUG-09 0930 1015 14 3 AY03
276 03-MAY-09 0830 0915 14 3 AY03
SELECT
coursenumber,
COUNT(CASE WHEN datestart BETWEEN (sysdate-365) AND sysdate THEN 1 END) AS Offered
FROM class
GROUP BY coursenumber;
So, as you can see, this particular problem doesn't need a join.
I think something like this should work for you, by just doing it as a subquery.
SELECT distinct c.coursenumber,
(SELECT COUNT(*)
FROM class
WHERE class.coursenumber = c.coursenumber
AND datestart BETWEEN (sysdate-365) AND sysdate
) AS Offered
FROM class c
I like jschoen's answer better for this particular case (when you want one and only one row and column out of the subquery for each row of the main query), but just to demonstrate another way to do it:
select t1.coursenumber, nvl(t2.cnt,0)
from class t1 left outer join (
select coursenumber, count(*) cnt
from class
where datestart between (sysdate-365) AND sysdate
group by coursenumber
) t2 on t1.coursenumber = t2.coursenumber