SQL query: confusing query - sql

I have the following tables:
Flights(flight_num, source_city, dest_city)
Departures(flight_num, date, plane_type)
Passengers(passenger_id, passenger_name, passenger_address)
Bookings(passenger_id, flight_num, date, seat_number)
And I want to find the number of departures for each type of plane for all flights that leave from Burbank. (Make sure the plane¬¬_type is also part of the result.)
So far I have
SELECT D.plane_type, COUNT(*)
FROM Departures D, Flights F
WHERE F.source_city = “Burbank”
AND F.flight_num = D.flight_num
GROUP BY D.plane_type
But I am not sure how to incorporate the fact that the planes might change for the same flight number?

You can not achieve that behaviour if yours plane_type changes with no rules.

Related

USING RECURSION IN SQL TO FIND THE LOCATION OF AN EVENT

I am trying to determine the location of an event from 2 tables using sql. I believe that recursion is necessary for this solution, and I'm a bit foggy on that. Any help you can provide would be appreciated.
The first table is the movement table. It shows when and where a person moved. I also included a movement rank, although, I'm not sure it's necessary for a solution. A person may move back and forth between buildings.
The second table is the event table. It shows a person and a time of that person's event.
What I want to be able to do is find, for each event in the event_table, the location of the person. The solution would look something like this:
Thank you so much for your time and consideration.
This does it. This leaves NULL in the column if there is no movement before that time.
SELECT et.*, (
SELECT to_location
FROM movement_table
WHERE person_id=et.person_id
AND movement_time < et.event_time
ORDER BY movement_time desc
LIMIT 1) AS event_location
FROM event_table et;
Output (from sqlite):
10|2021-07-20 11:30:00|
20|2021-06-29 10:29:00|
20|2021-07-02 04:30:00|BUILDING A
20|2021-07-04 15:46:00|BUILDING B
40|2021-07-07 23:59:00|BUILDING C
50|2021-07-13 23:05:00|BUILDING D
50|2021-07-17 09:37:00|BUILDING D
sqlite>
If I understand correctly, location for an event is the TO_LOCATION column of the latest movement before the event in the Movement_table. So you need to join tables and select by max(MOVEMENT_TIME) < (or <=) EVENT_TIME. I cannot give an exact sql but it will be something like:
Select e.event_time, m.to_location
From event_table e, movement_table m
Where m.movement_time =
(Select max(m1.movement_time)
From movement_table m1
Where m1.movement_time < e.event_time)
Basically, a person is in a place for a period of time. You really just need the time period -- to get the end time use lead(). The rest is a join:
select e.*, m.*
from events e left join
(select m.*,
lead(movement_time) over (partition by person_id order by movement_time) as next_movement_time
from movements m
) m
on e.person_id = m.person_id and
e.event_time >= m.movement_time and
(e.event_time < m.next_movement_time or m.next_movement_time is null);

SQL query , group by only one column

i want to group this query by project only because there are two records of same project but i only want one.
But when i add group by clause it asks me to add other columns as well by which grouping does not work.
*
DECLARE #Year varchar(75) = '2018'
DECLARE #von DateTime = '1.09.2018'
DECLARE #bis DateTime = '30.09.2018'
select new_projekt ,new_geschftsartname, new_mitarbeitername, new_stundensatz
from Filterednew_projektkondition ps
left join Filterednew_fakturierungsplan fp on ps.new_projekt = fp.new_hauptprojekt1
where ps.statecodename = 'Aktiv'
and fp.new_startdatum >= #von +'00:00:00'
and fp.new_enddatum <= #bis +'23:59:59'
--and new_projekt= Filterednew_projekt.new_
--group by new_projekt
*
look at the column new_projekt . row 2 and 3 has same project, but i want it to appear only once. Due to different other columns this is not possible.
if its of interested , there is another coluim projectcondition id which is unique for both
You can't ask a database to decide arbitrarily for you, which records should be thrown away when doing a group. You have to be precise and specific
Example, here is some data about a person:
Name, AddressZipCode
John Doe, 90210
John Doe, 12345
SELECT name, addresszipcode FROM person INNER JOIN address on address.personid = person.id
There are two addresses stored for this one guy, the person data is repeated in the output!
"I don't want that. I only want to see one line for this guy, together with his address"
Which address?
That's what you have to tell the database
"Well, obviously his current address"
And how do you denote that an address is current?
"It's the one with the null enddate"
SELECT name, addresszipcode FROM person INNER JOIN address on address.personid = person.id WHERE address.enddate = null
If you still get two addresses out, there are two address records that are null - you have data that is in violation of your business data modelling principles ("a person's address history shall have at most one adddress that is current, denoted by a null end date") - fix the data
"Why can't i just group by name?"
You can, but if you do, you still have to tell the database how to accumulate the non-name data that it shows you. You want an address data out of it, it has 2 it wants to show you, you have to tell it which to discard. You could do this:
SELECT name, MAX(addresszipcode) FROM person INNER JOIN address on address.personid = person.id GROUP BY name
"But I don't want the max zipcode? That doesn't make sense"
OK, use the MIN, the SUM, the AVG, anything that makes sense. If none of these make sense, then use something that does, like the address line that has the highest end date, or the lowest end date that is a future end date. If you only want one address on show you must decide how to boil that data down to just one record - you have to write the rule for the database to follow and no question about it you have to create a rule so make it a rule that describes what you actually want
Ok, so you created a rule - you want only the rows with the minimum new_stundenstatz
DECLARE #Year varchar(75) = '2018'
DECLARE #von DateTime = '1.09.2018'
DECLARE #bis DateTime = '30.09.2018'
select new_projekt ,new_geschftsartname, new_mitarbeitername, new_stundensatz
from
(SELECT *, ROW_NUMBER() OVER(PARTITON BY new_projekt ORDER BY new_stundensatz) rown FROM Filterednew_projektkondition) ps
left join
Filterednew_fakturierungsplan fp on ps.new_projekt = fp.new_hauptprojekt1
where ps.statecodename = 'Aktiv'
and fp.new_startdatum >= #von +'00:00:00'
and fp.new_enddatum <= #bis +'23:59:59'
and ps.rown = 1
Here I've used an analytic operation to number the rows in your PS table. They're numbered in order of ascending new_stundensatz, starting with 1. The numbering restarts when the new_projekt changes, so each new_projekt will have a number 1 row.. and then we make that a condition of the where
(Helpful side note for applying this technique in future.. Ff it were the FP table we were adding a row number to, we would need to put AND fp.rown= 1 in the ON clause, not the WHERE clause, because putting it in the where would make the LEFT join behave like an INNER, hiding rows that don't have any FP matching record)

How to sum employee paychecks from multiple jobs into one table

table featuring fictitious employee data, area ( in hectares (ha)) cleared (noted in french as superficie), rate for 1 hectare of cleared land on the specific lot (french:taux) and amount due( expr1) for that lot.
My problem here is that I want the total amount due for each Worker, not the amount due for each worker for each lot. Totals for Sirs Alain, Jacques, Paul, Roger and Tanguay should normally be 4066, 4082 , 5638, 5811 and 3131 , respectively.
My code so far is this
SELECT tbl_Employés.Num_deb, tbl_Employés.Prénom, tbl_Employés.Nom, tbl_Employés.Age, tbl_Employés.DEP, tbl_Employés.Expérience, tbl_Employés.Adresse, Tbl_terrain.superficie, Tbl_terrain.Taux, [superficie]*[taux] AS [Montant à payer]
FROM tbl_Employés INNER JOIN Tbl_terrain ON tbl_Employés.Num_deb = Tbl_terrain.Num_deb
ORDER BY tbl_Employés.Nom;
I have so far tried to use GROUP BY Numéro_terrain, which returns an error that my query does not include the specified expression ''Num_deb'' as a part of an aggregation fuction
I woul greatly appreciate any imput. I am very sorry if you have a hard time understanding some words, as I am doing my best to translate everything from french.
One method is to include all the columns in the GROUP BY that are not arguments to aggregation functions:
SELECT e.Num_deb, e.Prénom, e.Nom, e.Age, e.DEP, e.Expérience, e.Adresse,
SUM([superficie]*[taux]) AS [Montant à payer]
FROM tbl_Employés as e INNER JOIN
Tbl_terrain as t
ON e.Num_deb = t.Num_deb
GROUP BY e.Num_deb, e.Prénom, e.Nom, e.Age, e.DEP, e.Expérience, e.Adresse
ORDER BY e.Nom;

Calculating Dates

I have this problem: List of customers with their next scheduled, reoccurring appointment, that is either yearly, monthly, or quarterly.
The tables\columns I have are:
customer
customer_ID
service
customer_ID
service_RecID
Resource
service_RecID
Recurrence_RecID
Date_Time_Start
Recurrence
Recurrence_RecID
RecurType
RecurInterval
DaysOfWeek
AbsDayNbr
SelectInterval
It is modeled such that when the schedule is setup, the date_start_time is the date of when the first reoccurring appointment took place. Ex.
Recurrence_RecID = 10
RecurType = m (could be y, or d as well for yearly or daily)
RecurInterval = 6 (if recurType = y, this would mean every 6 years)
Given that the system generates these nightly, how would I write a query to calculate the next scheduled appointment, for each customer? I originally thought of using the Resource.Date_Time_Start and just cycling through until a variable nextAppointment >= today(), but is it good practice to run loops in SQL?
If anymore info is needed, let me know. Thank you much!
Edit: I will make a sqlfiddle.
I would suggest using a sub-query as opposed to looping. More efficient that way. This may not be exact but something like...
SELECT
*
FROM
(
SELECT
customer.customer_id,
service.service_RecID,
Resource.Date_Time_Start,
Recurrence.Recurrence_RecID,
RecurType,
RecurInterval,
DaysOfWeek,
AbsDayNbr,
SelectInterval,
NextAppointmentDate=
CASE
WHEN RecurType='m' THEN DATEADD(MONTH,RecurInterval,Resource.Date_Time_Start)
WHEN RecurType='y' THEN DATEADD(YEAR,RecurInterval,Resource.Date_Time_Start)
ELSE
NULL
END
FROM
Recurrence
INNER JOIN Resource ON Resource.Recurrence_RecID=Recurrence.Recurrence_RecID
INNER JOIN service ON service.service_RecID=Resource.service_RecID
INNER JOIN customer ON customer.customer_ID=service.customerID
)AS X
WHERE
NextAppointmentDate>=GETDATE()
ORDER BY Fields...

sql queries to show the most popular record

I have four tables
Car (car_ registration_no, class, type_code)
Rental_history (rent_date, car_registration_no, rent_location_code, return_location_code)
Type (type_code, make, model)
Location (location_code, branch_name)
I need a query to show the most popular car rented by location.
I need a query to show the total rentals at each location for the previous month?
My code so far is as follows, but I couldn't complete it:
SELECT car.class, car.type_code , type.make, type.model
FROM car , type, rental_history
where rental_history.car_registration_no = car.car_registration_no
and car.type_code = type.type_code
You will need to join the tables and calculate the numbers. Let's start off with an easier query to point you in the right direction.
This will show you how many times a "type_code" car has been rented per location (untested, may contain errors)
SELECT
count(car.car_registration_no) as rental_num,
car.type_code,
rental_history.rent_location_code
FROM car
LEFT JOIN rental_history ON (rental_history.car_registration_no = car.car_registration_no)
GROUP BY car.type_code, rental_history.rent_location_code;
I'm using a left join here because there may be cars that have not been rented and won't have any history. Instead of not showing up, you will have a "0" for number of rentals.
Edit:
For the second query it's actually very straightforward. You need to group by location, filter on date and use COUNT (again, untested):
SELECT
count(rental_history.car_registration_no) as rental_num,
rental_history.rent_location_code
FROM rental_history
WHERE rent_date >= '2012-03-01' AND rent_date < '2012-04-01'
GROUP BY rental_history.rent_location_code;
Join All the table and use count..!