I have two tables like this
rooms
id | number
1 | 111
2 | 112
occupied_rooms
id | check_in | check_out | room_id
1 | 2017-10-01 | 2017-10-04 | 1
I want to get all the unoccupied rooms according to date check_in and check_out for this I tried
select r.id
, r.number
from rooms r
left join occupied_rooms o
on r.id = o.room_id
where (o.check_in not between "2017-10-05" and "2017-10-08" )
or (o.check_in >= "2017-10-05" and o.check_out <= "2017-10-08"))
but this query giving me result like this. which is incorrect.
id | number
1 | 111
What is wrong with this query?
Thank you for your any help and suggestions
Just join the two tables on the condition that the id matches and the range of intended stay overlaps with the range in the occupied_rooms table.
SELECT r.*
FROM rooms r
LEFT JOIN occupied_rooms t
ON r.id = t.id AND
('2017-10-02' <= t.check_out AND '2017-10-03' >= t.check_in)
WHERE
t.id IS NULL; -- NULL value indicates the room did not overlap
-- with any existing reservations
You can also check out this great reference question on how to deal with overlapping ranges in SQL queries. It makes the problem you are facing much simpler.
Demo
Your data in table occupied_rooms meets the first condition in "where";
check_in date(2017-10-01) is not between "2017-10-05" and "2017-10-08" and your where is or.
Thus, the result is included this data.
Can you tell us what output you expect?
Related
I have two tables looking like this
Patient (table 1)
id | name
------------
1 | robel
2 | dave
Patient_followup (table 2)
id | Patient_id | date_created
-----------------------
1 | ---- 1 -- | 01/01/2015
2 | -----1 -- | 01/07/2016
I want to display all the patients with their perspective latest followup data. so i tried using this query
Select * from patient
left join Patient_followup pf on pf.Patient_id = patient.id
order by pf.date_created
Limit 1
but this is giving me only the first patient robel. i tryed removing the limit and its giving me two records of robel and one record of dave because robel has two followup data. so what should i do to get only one record of each patient ?
Try this:
Select
*
from
patient
left join
(SELECT
id as pf_id,
MAX(date_created) as latest_followup_date,
Patient_id
FROM
Patient_followup
GROUP BY
Patient_id) as pf
ON pf.Patient_id = patient.id
As mentioned by anton in the first comment, you need to use aggregation to get one record per patient.
Select patient.*,MAX(pf.date_created) as followupdate,group_concat(pf.date_created) from patient
left join Patient_followup pf on pf.Patient_id = p.patient.id
group by patient.id
order by pf.date_created
Here, you will get your values comma separated.
1) "Limit 1" will only return the first result. Typically this is used if the query will result in a very large result set and you only want the first few results.
Ex:
"LIMIT 30" will show the first 30 rows of the query.
2) I would change to setup of the tables so the query is smoother. Right now, you create a new line for each follow-up date even if the patient is already created. You could add another column in the table named "FollowUpDate". That way each patient record has the table id, patient id, creation date and followup date in the same row. That way, each patient has only one row.
EX:
Patient (table 1)
id | name | created_date | next_followup_date |
1 | Robel | 01/01/2015 | 01/01/2016 |
2 | Dave |[created_date]| [next_follup_date] |
Patient_followup (table 2)
id | Patient_id | date_created | followUpDate |
1 | 1 | 01/01/2015 | 06/01/2016 | // example date
2 | 1 | 01/01/2015 | 01/01/2016 |
3 | 2 |[date created]| [FollowUpDate] |
3) Change query to:
Use this select statement to get all patient records.
Select * from patient
left join Patient_followup pf on pf.Patient_id = patient.id
order by pf.Patient_id
Use this select statement to get the specific patient record information.
Select * from patient
inner join Patient_followup pf on pf.Patient_id = patient.id
where patient.id = 1 //to get robel. Edit this line as necessary, perhaps by user input...
order by pf.followUpDate
NOTE: When you insert a new record in Patient_followup, make sure you update Patient.next_followup_date.
I hope this helps!
Here is my SQLFIDDLE
Basically I have three tables, A issues, journals and journal details.
I would like to have in a single query the following way of representation.
id | status_id | X |
90001 | 12 | NULL |
90002 | 12 | NULL |
90003 | 12 | 2015-01-06 |
90004 | 12 | 2015-01-09 |
The rule applied is for X is the max 'journals' created date at which the 'fixed_version_id' == 55 exists.
Please help.
Thank You,
I recommend you start by getting the details of all the journals that meet your requirement like this:
SELECT *
FROM journal_details
WHERE property = 'fixed_version_id' AND value = '55';
Then you can use those values to get the created date of the journal rows that meet this requirement:
SELECT j.issue_id, MAX(j.created_on) AS created_on
FROM journals j
JOIN journal_details jd ON jd.journal_id = j.id AND jd.property = 'fixed_version_id' AND jd.value = '55'
GROUP BY j.issue_id;
From these results, you can join in to get all issues. If you use an outer join, you'll get null for any journals that didn't meet the criteria:
SELECT i.id, i.status_id, tmp.created_on
FROM issues i
LEFT JOIN(
SELECT j.issue_id, MAX(j.created_on) AS created_on
FROM journals j
JOIN journal_details jd ON jd.journal_id = j.id AND jd.property = 'fixed_version_id' AND jd.value = '55'
GROUP BY j.issue_id
) tmp ON tmp.issue_id = i.id;
Here is an SQL Fiddle example.
I've been trying to solve this without a post, but i can't find a fitting answer...
I have a SALE-Table and an APPOINTMENT-Table.
In both is a coloumn sale_id.
In APPOINTMENT is the column do_by(date) which can have several entries per sale_id.
What I need is the NEXT appointment PER matching sale_id.
Sth. like this:
appointment_id | sale_id | do_by
--------------------------------------
1365 | 160 | 27.05.2014
2546 | 173 | 29.05.2014
5483 | 265 | 01.06.2014
So far my Query only gives me the smallest do_by of ALL...
SELECT a.appointment_id, a.do_by, s.sale_id
FROM [Askus7].[CRM7].[APPOINTMENT] a, [Askus7].[CRM7].[SALE] s
WHERE (s.sale_id = a.sale_id) AND a.do_by =
(
SELECT MIN(a2.do_by)
FROM [Askus7].[CRM7].[APPOINTMENT] a2, [Askus7].[CRM7].[SALE] s2
WHERE s2.sale_id = a2.sale_id
AND s.sale_id = a.sale_id
)
Thx for your help!
Something like that? (untested)
SELECT a.appointment_id, ms.do_by, a.sale_id
(
SELECT a2.sale_id as sale_id, MIN(a2.do_by) as do_by
FROM [Askus7].[CRM7].[APPOINTMENT] a2 JOIN [Askus7].[CRM7].[SALE] s2
ON a2.sale_id=s2.sale_id
GROUP BY a2.sale_id
)ms
JOIN [Askus7].[CRM7].[APPOINTMENT] a
ON a.sale_id = ms.sale_id and a.do_by = ms.do_by;
warning: if you don't have do_by column indexed and your APPOINTMENT table is large, the query might be quite slow.
I have the following SQL query which queries my tickets, ticketThreads, users and threadStatus tables:
SELECT tickets.threadId, ticketThreads.threadSubject, tickets.ticketCreatedDate, ticketThreads.threadCreatedDate, threadStatus.threadStatus, users.name
FROM
tickets
INNER JOIN
ticketThreads
ON
tickets.threadId = ticketThreads.threadId
INNER JOIN
threadStatus
ON
ticketThreads.threadStatus = threadStatus.id
INNER JOIN
users
ON
users.id = ticketThreads.threadUserId
WHERE
tickets.ticketId = ticketThreads.lastMessage
AND
ticketThreads.threadStatus != 3
ORDER BY
tickets.ticketCreatedDate
DESC
The abridged version of what this returns is:
threadId |
----------
1 |
2 |
This works fine, and is what I expect, however to clean up the code and database slightly I need to remove the ticketThreads.lastMessage column.
If I remove the line WHERE tickets.ticketId = ticketThreads.lastMessage then this is an abridged version of what is returned:
threadId |
----------
1 |
2 |
1 |
What I need to do then is edit the query above to enable me to select the highest unique value for each threadId value in the tickets database.
I know about MAX() and GROUP BY but can't figure how to get them into my query above.
The relevant parts of the tables are shown below:
tickets
ticketId | ticketUserId | threadId
-------------------------------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 1
ticketThreads
threadId | lastMessage | threadStatus
-------------------------------
1 | 3 | 4
2 | 2 | 1
I hope all the above is clear and makes sense
So you need the ticket with the highest id per each thread? Your problem is actually very easy variant of greatest record per group problem. No need for any subqueries. Basicaly you have two options, which both should perform much better than your query, the second be faster (please post the actual durations in your db!):
1. Standard compliant query, but slower:
SELECT t1.threadId, ticketThreads.threadSubject, t1.ticketCreatedDate,
ticketThreads.threadCreatedDate, threadStatus.threadStatus, users.name
FROM tickets as t1
LEFT JOIN tickets as t2
ON t1.threadId = t2.threadId AND t1.ticketId < t2.ticketId
JOIN ticketThreads ON t1.threadId = ticketThreads.threadId
JOIN threadStatus ON ticketThreads.threadStatus = threadStatus.id
JOIN users ON users.id = ticketThreads.threadUserId
WHERE t2.threadId is NULL
AND ticketThreads.threadStatus != 3
ORDER BY t1.ticketCreatedDate DESC
This one joins the tickets table two times, which can make it a bit slower for big tables.
2. Faster, but uses MySQL extension to standard SQL:
set #prev_thread := NULL;
SELECT t.threadId, ticketThreads.threadSubject, t.ticketCreatedDate,
ticketThreads.threadCreatedDate, threadStatus.threadStatus, users.name
FROM tickets as t
JOIN ticketThreads ON t.threadId = ticketThreads.threadId
JOIN threadStatus ON ticketThreads.threadStatus = threadStatus.id
JOIN users ON users.id = ticketThreads.threadUserId
WHERE ticketThreads.threadStatus != 3
AND IF(IFNULL(#prev_thread, -1) = #prev_thread := t.threadId, 0, 1)
ORDER BY t.threadId, t.ticketId DESC,
t.ticketCreatedDate DESC
Here, we perform one pass scan on ordered joined data, using auxiliary mysql variable #prev_thread to filter only the first (in the given order) ticket for each thread (the one with highest ticketId).
I'm having a hard time wrapping my mind around this, any assistance is most appreciated.
I have two select statements with joins to 1 or more tables.
SELECT repinfo.repName, SUM(callstatssummary.CallsIn)
FROM repinfo
LEFT JOIN callstatssummary
ON repinfo.isaacID = callstatssummary.IsaacID AND callstatssummary.ShiftDate >= '2013-02-10' AND callstatssummary.ShiftDate <= '2013-02-16'
GROUP BY repinfo.repName;
The output of the first statement is a list of everyone in the repinfo table, with the sum of the total calls they took during the week. I used a left join to include people who didn't take calls in the result.
SELECT repinfo.repName, SUM(`1036`.afterRgu) - SUM(`1036`.priorRgu)
FROM repinfo
JOIN reporders
ON repinfo.repID = reporders.oRep
JOIN `1036`
ON reporders.workOrder = `1036`.workOrder AND `1036`.entryDate >= '2013-02-10' AND `1036`.entryDate <= '2013-02-16' AND `1036`.afterRgu >= `1036`.priorRgu
GROUP BY repinfo.repName;
The second statement outputs the number of products that each person sold during the week. The repinfo table has the information about the representative, which joins with the reporders table to match the work order. The 1036 table has detailed information about the orders.
I am looking to output something like this - essentially combine the output of the two select statements:
| repName | SUM(callstatssummary.CallsIn) | SUM(`1036`.afterRgu) - SUM(`1036`.priorRgu) |
______________________________________________________________________________________________
| Bruce W | 41 | 13 |
| Cathy M | 84 | 17 |
| Jonah S | NULL | 29 |
Any suggestions?
One way to combine those statements is to make each of them a derived-table / inline-view and join on repName.
Please note: Obviously you would want to join on a rep ID number (or whatever you call the primary key of the repinfo table) if two reps can have the same name.
select
r.repName, c.sumCallsIn, o.sumProdSold
from
repinfo r
left join (
SELECT repinfo.repName,
SUM(callstatssummary.CallsIn) sumCallsIn
FROM repinfo
LEFT JOIN callstatssummary
ON repinfo.isaacID = callstatssummary.IsaacID
AND callstatssummary.ShiftDate >= '2013-02-10'
AND callstatssummary.ShiftDate <= '2013-02-16'
GROUP BY repinfo.repName
) c
on c.repName = r.repName
left join (
SELECT repinfo.repName,
SUM(`1036`.afterRgu) - SUM(`1036`.priorRgu) sumProdSold
FROM repinfo
JOIN reporders
ON repinfo.repID = reporders.oRep
JOIN `1036`
ON reporders.workOrder = `1036`.workOrder
AND `1036`.entryDate >= '2013-02-10'
AND `1036`.entryDate <= '2013-02-16'
AND `1036`.afterRgu >= `1036`.priorRgu
GROUP BY repinfo.repName
) o
on r.repName = o.repName
order by r.repName;