MySQL right outer join query - mysql

I have a query regarding a query in MySQL.
I have 2 tables one containing SalesRep details like name, email, etc. I have another table with the sales data which has reportDate, customers served and link to the salesrep via a foreign key. One thing to note is that the reportDate is always a friday.
So the requirement is this: I need to find sales data for a 13 week period for a given list of sales reps - with 0 as customers served if on a particular friday there is no data. The query result is consumed by a Java application which relies on the 13 rows of data per sales rep.
I have created a table with all the Friday dates populated and wrote a outer join like below:
select * from (
select name, customersServed, reportDate
from Sales_Data salesData
join `SALES_REPRESENTATIVE` salesRep on salesRep.`employeeId` = salesData.`employeeId`
where employeeId = 1
) as result
right outer join fridays on fridays.datefield = reportDate
where fridays.datefield between '2014-10-01' and '2014-12-31'
order by datefield
Now my doubts:
Is there any way where i can get the name to be populated for all 13 rows in the above query?
If there are 2 sales reps, I'd like to use a IN clause and expect 26 rows in total - 13 rows per sales person (even if there is no record for that person, I'd still like to see 13 rows of nulls), and 39 for 3 sales reps
Can these be done in MySql and if so, can anyone point me in the right direction?

You must first select your lines (without customersServed) and then make an outer join for the customerServed
something like that:
select records.name, records.datefield, IFNULL(salesRep.customersServed,0)
from (
select employeeId, name, datefield
from `SALES_REPRESENTATIVE`, fridays
where fridays.datefield between '2014-10-01' and '2014-12-31'
and employeeId in (...)
) as records
left outer join `Sales_Data` salesData on (salesData.employeeId = records.employeeId and salesData.reportDate = records.datefield)
order by records.name, records.datefield

You'll have to do 2 level nesting, in your nested query change to outer join for salesrep, so you have atleast 1 record for each rep, then a join with fridays without any condition to have atleast 13 record for each rep, then final right outer join with condition (fridays.datefield = innerfriday.datefield and (reportDate is null or reportDate=innerfriday.datefield))
Very inefficient, try to do it in code except for very small data.

Related

How to write an sql query that calculate sales monthly for a particular year?

I have a database that contain a record from 2017-2021. But I need an sql code to calculate sales monthly for just 2017 alone.
It's a two different table I'm trying to call in the coding
SELECT sum(itemPrice) From article,
Month(TransactionDate) FROM transactionid WHERE
year(TransactionDate) = 2017 group by 1
If I understand your query properly, it looks like you have 2 tables called article and transactionid. I assume these 2 tables have a relationship together which I called article_id in the example below.
This would be pretty close to what you need, you just need set the correct column names:
SELECT MONTH(TransactionDate) as month, SUM(itemPrice) as total_sales
FROM article
JOIN transactionid ON transactionid.article_id = article.id
WHERE YEAR(TransactionDate) = 2017
GROUP BY MONTH(TransactionDate)
ORDER BY month;

Get data from between two dates

I have these two tables
The first one is expenses table and the second one is expensename
Exp_Type(first table) is the Expense name(second table) as 2 is Food
I am trying to group expense according to expense type and get data between certain dates.
This is what i have tried, but it wont work.
select
(select
(select name from EXPENSENAME where id=EXP_TYPE)as ExpenseType,
sum(PRICE) as cost
from EXPENSES WHERE USERID=1 GROUP BY EXPENSES.EXP_TYPE),
[date]
from EXPENSES where [date] BETWEEN '10-09-2015' and '10-18-2015 23:59:59'
And
select
(select name from EXPENSENAME where id=EXP_TYPE)as ExpenseType,
sum(PRICE) as cost,
date
from EXPENSES WHERE USERID=1 and DATE BETWEEN '01/10/2015' and '29/10/2015' GROUP BY EXPENSES.EXP_TYPE
With out date, i am getting result by this query but i need the same data between certain dates,please help
select
(select name from EXPENSENAME where id=EXP_TYPE)as ExpenseType,
sum(PRICE) as cost
from EXPENSES WHERE USERID=1 GROUP BY EXPENSES.EXP_TYPE
you want to join the tables together
SELECT en.name as ExpenseType, SUM(e.price) as cost
FROM expenses e
JOIN expensename en ON en.id = e.exp_type
WHERE e.date BETWEEN '10-09-2015' and '10-18-2015'
GROUP BY en.name
this should give you the cost per name
the current query you have is TERRIBLE... and this is why
SELECT (SELECT ... FROM ... WHERE ... ) as ...
this is creating a correlated subquery which is executing once for every row of the parent select. meaning if you have a table with 4 rows in it (SELECT ... FROM ... WHERE ... ) will execute 4 times scanning 16 rows (assuming its from the same table) in general that is a really really bad way to get data... if you have a million rows... well do the math, its a bad idea

how to write a Query in Mysql

I have 2 tables.ms_expese and track_expense.Using this table generate a fact table
I want the expense_name in ms_expense,expense_amount from track_expense.
I want to get the sum of expense_amount for a particular expense_name based on date.The date in the order of 1,2...12 as month id
SELECT DATE_Format(a.date,'%b') as month_id,b.expense_name AS expense_type, sum(a.expense_amount) AS expense_amount FROM ms_expense b JOIN track_expense a on a.`expense_id`=b.`expense_id` group by DATE_Format(a.date,'%b')
how to put the month id in the order of 1,2,..12 and my date format y-m-d
I get the month in apr,aug and so on but i need jan as 1,feb as 2
I have 25 expenses(expense name).In this query i got the total expense amount of first expense only.I want the total expense of all expenses in every month
CREATE TABLE fact AS
(<your select query>)
Your select query can be in the following form
SELECT MONTH(date)as month_id,expense_name,sum(expense_amount)
FROM ms_expense JOIN track_expense using (expense_id)
group by expense_name,MONTH(date)

How to filter out records from one table where its id occurs in a column of another table

I have 2 MySQL tables
tableRooms contains the rooms of a hotel
tableRoomsBooked contains the booked dates of the rooms
I need an SQL query that returns the rooms that have no bookings between 2 given dates. This is what I have got so far:
SELECT * FROM `tableRooms`
LEFT JOIN `tableRoomsBooked`
ON `tableRooms`.`id` = `tableRoomsBooked`.`room_id`
WHERE (date BETWEEN '2015-01-02' AND '2015-01-30')
....?
The query should only get the room_id 2 because room 2 has no bookings in this period.
What should my query be like?
select *
from tableRooms
where id not in (
select distinct room_id
from tableRoomsBooked
where date between '2015-01-02' and '2015-01-30'
)
This will select the list of existing IDs in a sub request, then exclude them from the main request.
Anyway, you should change the name of "date" column, because "date" can be confusing as soon as it is a data type too.

SQL maximum number of records with a common value

Please consider the following two tables:
Holidays
HolidayID (PK)
Destination
Length
MaximumNumber
...
Bookings
BookingID (PK)
HolidayID (FK)
Name
...
Customers can book holidays (e.g. go to Hawaii). But, suppose that a given holiday has a maximum number of places. e.g. there are only 75 holidays to Hawaii this year (ignoring other years).
So if some customer wants to book a holiday to Hawaii. I need to count the records in Bookings table, and if that number is greater than 75 I have to tell the customer it's too late.
This I can do using 2 MySQL queries (1 to get MaximumNumber for the holiday, 2 to get the current total from Bookings) and PHP (for example) to compare the count value with the maximum number of Hawaii holidays.
But I want to know if there is a way to do this purely in SQL (MySQL in this case)? i.e. count the number of bookings for Hawaii and compare against Hawaii's MaximumNumber value.
EDIT:
My method:
$query1 = "SELECT MaximumNumber FROM Holidays WHERE HolidayID=$hawaiiID";
$query2 = "SELECT COUNT(BookingID) FROM Bookings WHERE HolidayID=$hawaiiID";
So if the first query gives 75 and the second query gives 75 I can compare these values in PHP. But I wondered if there was a way to do this somehow in SQL alone.
Maybe I am missing something, but why not use a subquery to determine the total bookings for each holidayid:
select *
from holidays h
left join
(
select count(*) TotalBooked, HolidayId
from bookings
group by holidayId
) b
on h.holidayId = b.holidayId
WHERE h.HolidayID=$hawaiiID;
See SQL Fiddle with Demo.
Then you could use a CASE expression to compare the TotalBooked to the MaxNumber similar to this:
select h.destination,
case
when b.totalbooked = h.maxNumber
then 'Not Available'
else 'You can still book' end Availability
from holidays h
left join
(
select count(*) TotalBooked, HolidayId
from bookings
group by holidayId
) b
on h.holidayId = b.holidayId
WHERE h.HolidayID=$hawaiiID;
See SQL Fiddle with Demo.
You will notice that I used a LEFT JOIN which will return all rows from the Holidays table even if there are not matching rows in the Bookings table.
Something like this will work. You can fill in the details:
select case
when
(select count(*)
from Bookings
where holidayID = $hawaiiid)
<= MaximumNumber then 'available' else 'sold out' end status
from holidays
etc
You might try something like this:
select case when b.freq < h.MaximumNumber
then 'Available'
else 'Not Available'
end as MyResult
from Holidays h
left join (
select HolidayID
, count(*) as freq
from Bookings
where HolidayID=$hawaiiID
group by HolidayID
) b
on h.HolidayID=b.HolidayID