SQL Divide one count result by another OR Alternate solution - sql

I have a table with the following schema.
Relational Database Schema:
Hotel = hotelNo, hotelName, city
Room = roomNo, hotelNo(FK), type, rate
Guest = guestNo, guestName, guestAddress
Booking = hotelNo(FK), guestNo(FK), dateFrom, dateTo, roomNo(FK)
There are entries in each table however their data isn't completely relevant to this question.
I need to calculate the average number of booking made for each hotel, ensuring that I include the hotels which do not currently have bookings.
I have this :
-- Call this select 1
select count(*)
from booking b, hotel h
where b.hotelNo=h.hotelNo;
-- Call this select 2
select count(*)
from hotel;
Select 1 returns the total number of bookings. Select 2 returns the total number of hotels. If I could simply divide the output of count in select 1 by the output of count in select 2 I would have my answer.
If this is possible can someone please help me with the code, otherwise can someone think of an alternate solution to achieve the same result?

If by "average number of bookings", you just want to divide the two numbers, then you can do:
select count(b.HotelNo) / count(distinct h.hotelNo)
from hotel h left join
booking b
on h.hotelNo = b.hotelNo;

Create a view say temp to get count of rooms per hotel[ The data you 'see' in a view, is not actually stored anywhere, and is generated from the tables on the fly.]
create view temp
as select hotelNo,count(*) as cnt from room group by hotelNo;
Use following query to fetch avg.
select booking.hotelNo,count(*) / cnt
from booking ,temp
where booking.hotelNo = temp.hotelNo
group by booking.hotelNo;
or
select booking.hotelNo,count(*) / cnt
from booking
INNER JOIN temp
on booking.hotelNo = temp.hotelNo
group by booking.hotelNo;
This will not include hotels that do not have any booking.

Related

Get rows from primary table, and also a count of how many times that record appears in a secondary table (including 0's)

I have a Dogs table, a Kennels table and Visits table that contains DogId and KennelId columns.
I am trying to get a full list of all the dogs, with a column showing the number of visits to a particular kennel, so many of the results will contain a 0 as the visit count.
This is what I've tried:
select dog.*, visits.visitCount FROM
(select * from Dogs) as dog,
(select COUNT (Visits.Id) as visitCount from Visits INNER JOIN Dogs ON Dogs.Id =
Visits.DogId where KennelId = 'E15A8C60-E0FE-472D-9CC4-08DA251A992F') as visits
With this statement, I end up with all of the dogs, but with the same visit count for all, which is incorrect. I assume my count function is simply executed once with the result repeated for the remaining rows. I do not know how to correct this. Any help will be much appreciated!
With no table schemas or sample data, a guess would be something like the following:
select d.*, Coalesce(v.VisitCount,0) VisitCount
from dogs d
left join (
select DogId, Count(*) VisitCount
from visits v
where v.KennedId = 'E15A8C60-E0FE-472D-9CC4-08DA251A992F'
group by DogId
)v on v.DogId = d.DogId;

how to list booking ref code and names of passengers in bookings with 3 or more passengers together with sql

here is the dataset 'ticket'
I need to retrieve a list of book_ref and names passengers in bookings with 3 or more passengers together .
I tried store the result in existed table booking_code
INSERT INTO booking_code
SELECT book_ref, passenger_name
FROM bookings.ticket
GROUP BY book_ref, passenger_name
/*looking for br have 2 airport
*/
HAVING COUNT( * ) >2;
but the result was 2 empty column of book_ref and passenger_name
I think I did not correctly use "count".
how can i fix to code so the outcome would be like this?
You seem to want window functions:
SELECT t.book_ref, t.passenger_name
FROM (SELECT t.*, COUNT(*) OVER (PARTITION BY book_ref) as book_ref_cnt
FROM bookings.ticket t
) t
WHERE book_ref_cnt > 2;
This returns booking with more than 2 passengers in the original data.

Get a column from each Table

I'm working with SQL Server 2008
I have 2 tables and I want to get 2 columns from the 1st table and 1 column from the 2nd table
when I make JOIN it gives me another things...
here is my code:
Select SUM(Sales.CDnum) as CDnum, SUM(Sales.Total) as TotalMoney,
SUM(Expenses.Costs) as Expenses, SUM(Sales.Total - Expenses.Costs) as Winnings
from Sales
JOIN Expenses
ON Sales.ID = Expenses.ID
but when I execute the code it gives me only one raw from the 1st table and 1 raw from the second ... because I have 1 raw in the 2nd table and 1st I have many raws...
someone can help me....
as I see ID columns are not related to each other in both tables, so you need to union them, for example like in this query:
select sum(q.sales), sum(q.expense), sum(q.sales)-sum(q.expense) as winnings
from (
select sum(Sales.Total) as sales, 0 as expense from Sales
union all
select 0 as sales, sum(Expenses.Costs) as expense from Expenses
) as q

SQL Grouping / Contract Value

I know this is going to be a simple one but after a midnight run at other coding my SQL brain is fried so I'm just reaching out for some quick help. I've got a test table with Agent, AgentID, Parent Account, AccountID, and TCV. What I need to do is pull all the agent/account IDs where the AccountIDs belong to an aggregate parent account under that agents name >= 10K.
So in this example, John has 2 accounts under the parent account ABC123 and since their total value is >=10K, these 2 would get pulled. But notice below where Jane has 2 accounts likewise under ABC123 but b/c their total value in her name is < 10K, they would not be pulled. So the results would be something like this:
Essetially I need to pull all AccountIDs where the total value of the parent account they roll-up to for that person is >= 10K. BTW, I'm using SQL Server Management Studio R2.
You just do a simple group by/having to get a list of agentids/parentaccounts that meet the 10k criteria. Then you can use that in a sub-select to join back to the same table and get the list of account ids
select agentid, accountid
from table t
inner join (
select agentid, parentaccount
from table
group by agentid, parentaccount
having sum(tcv) >= 10000
) t1
on t.agentid = t1.agentid
and t.parentaccount = t1.parentaccount
;WITH MyCTE AS
(
SELECT AgentID,
ParentAccount,
SUM(TCV) AS Total
FROM TableName
GROUP BY AgentID,
ParentAccount
)
SELECT T.AgentId, T.AccountId
FROM Table T
JOIN MyCTE M
ON M.AgentId = T.AgentId
AND M.ParentAccount= T.ParentAccount
WHERE M.Total>10000

Display full records of duplicate entries across multiple columns

I have a table (customers) that includes fields telephone_1, telephone_2, telephone_3 & telephone_4.
What I need to see is full records of where any telephone numbers are used in other customers - as I believe something has gone wrong with the data somewhere and customer numbers are duplicated into each other!
I have tried the below code, but this doesn't give me what I want as only compares 1/1, 2/2, 3/3 & 4/4. I have an ID field which can be used to differentiate between records.
SELECT *
FROM Customers AS a
WHERE 1 < (SELECT Count(*)
FROM Customers AS b
WHERE a.Telephone_1 = b.Telephone_1
OR a.Telephone_2 = b.Telephone_2
OR a.Telephone_3 = b.Telephone_3
OR a.Telephone_4 = b.Telephone_4
Any assistance is appreciated - thanks!
How about this?
SELECT *
FROM Customers AS a
WHERE 1 < (
SELECT Count(*)
FROM Customers AS b
WHERE a.Telephone_1 IN (b.Telephone_1, b.Telephone_2, b.Telephone_3, b.Telephone_4)
OR a.Telephone_2 IN (b.Telephone_1, b.Telephone_2, b.Telephone_3, b.Telephone_4)
OR a.Telephone_3 IN (b.Telephone_1, b.Telephone_2, b.Telephone_3, b.Telephone_4)
OR a.Telephone_4 IN (b.Telephone_1, b.Telephone_2, b.Telephone_3, b.Telephone_4)
)
========Take 2=======
Following the comments:
Create a new table with telephone numbers nd customer IDs
CREATE TABLE tempTelephoneNos (
INTEGER customer,
VARCHAR(32) telephoneNo
);
assuming those are the appropriate data types for the customer Id and phone no.
Populate the new table
INSERT INTO tempTelephoneNos (customer, telephoneNo)
SELECT customer_id, telephone_1
FROM customers
UNION ALL
SELECT customer_id, telephone_2
FROM customers
UNION ALL
SELECT customer_id, telephone_3
FROM customers
UNION ALL
SELECT customer_id, telephone_4
FROM customers
Then you can find out which telephone numbers appear for more than one customer with
SELECT customer, telephoneNo
FROM tempTelephoneNos
WHERE 1 < (SELECT COUNT(*) FROM tempTelephoneNos GROUP BY telephoneNo)