Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am beginner in sql. Anyone please tell me the problem of my customised query.
select *
from Follow_My_Doct.tbl_hospital_registration h
INNER JOIN Follow_My_Doct.tbl_subscribed_packages s
ON s.hospitalId = h.id
AND s.active = 1
AND ( select max(sp.expireDate), sp.hospitalId
from Follow_My_Doct.tbl_subscribed_packages sp
where sp.active = 1
group by sp.hospitalId )
where h.hospital_active = 1
Error Code: 1241. Operand should contain 1 column(s)
Subscription table
hospital Id expireDate
145 2021-07-10
146 2021-06-10
147 2021-09-10
146 2021-10-10
You should put that subquery with the max and group by inside an INNER JOIN clause.
select *
from Follow_My_Doct.tbl_hospital_registration h
INNER JOIN ( select max(sp.expireDate) maxexpiredate, sp.hospitalId
from Follow_My_Doct.tbl_subscribed_packages sp
where sp.active = 1
group by sp.hospitalId ) as s
ON s.hospitalId = h.id
where h.hospital_active = 1
Since I don't have your data tables, I made up one environment to test that query by using table variables. The example below is for SQL Server, but the query works fine for MySQL, which currently I don't have installed on my machine.
declare #tbl_subscribed_packages TABLE(
hospitalId int,
active bit,
expiredate datetime
)
declare #tbl_hospital_registration table(
id int,
hospital_active bit)
Now populate tables with data:
insert #tbl_hospital_registration
values (145,1),(146,1),(147,1)
insert #tbl_subscribed_packages
values (145,1,'2021-07-10')
,(146,1,'2021-06-10')
,(147,1,'2021-09-10')
,(146,1,'2021-10-10')
Then, I test the query against these data
select *
from #tbl_hospital_registration h
INNER JOIN ( select max(sp.expireDate) maxexpiredate, sp.hospitalId
from #tbl_subscribed_packages sp
where sp.active = 1
group by sp.hospitalId ) as s
ON s.hospitalId = h.id
where h.hospital_active = 1
Note that using subquery as a view in INNER JOIN, I should add an alias name for max(expireDate) column.
The result is:
id
hospital_active
maxexpiredate
hospitalId
145
1
2021-07-10 00:00:00.000
145
146
1
2021-10-10 00:00:00.000
146
147
1
2021-09-10 00:00:00.000
147
Is that what you want?
6th line has issues. After AND you should have condition but you have sub query returns two column values
You can try the below - using row_number()
select * from
(
select *,row_number() over(partition by s.hospitalId order by expireDate desc ) as rn from
Follow_My_Doct.tbl_hospital_registration h INNER JOIN Follow_My_Doct.tbl_subscribed_packages s
ON s.hospitalId = h.id
where h.hospital_active = 1 and s.active = 1
)A where rn=1
Related
My table is:
id
student_id
exam_date
license
result
1
101
01-11-2020
B2
FAILED
2
102
15-11-2020
A
PASSED
3
103
22-11-2020
D
FAILED
4
101
01-10-2020
D
PASSED
5
104
01-12-2020
A
PASSED
6
103
29-11-2020
D
PASSED
7
101
01-12-2020
B2
PASSED
8
105
01-09-2020
B2
FAILED
9
104
01-11-2020
A
FAILED
10
105
01-11-2020
B2
PASSED
I need to select the results that would have the first result according to the exam date according to each student id and the license column. If the same student takes different license exam, these two results need to come up as well. But I need only one result row for each student id and license value.
The result should look like this:
id
student_id
exam_date
license
result
1
101
01-11-2020
B2
FAILED
2
102
15-11-2020
A
PASSED
3
103
22-11-2020
D
FAILED
4
101
01-10-2020
D
PASSED
8
105
01-09-2020
B2
FAILED
9
104
01-11-2020
A
FAILED
I've done the research and queries and so far I only got 1 row for student_id although the student takes two different license examination.
The following is my query:
SELECT scct_outer.id, scct_outer.stud_id, scct_outer.exam_date, scct_outer.license, scct_outer.result
FROM stud_cdl_comp_test AS scct_outer
INNER JOIN
(SELECT stud_id, MIN(exam_date) AS MinExamDate
FROM stud_cdl_comp_test AS scct
INNER JOIN stud AS s ON scct.stud_id = s.id
INNER JOIN agent_profile AS ap ON s.agent_profile_id = ap.id
GROUP BY stud_id) groupedscct
ON scct_outer.stud_id = groupedscct.stud_id
AND scct_outer.exam_date = groupedscct.MinExamDate
The problem with you original code is that it is missing a correlartion on the licences between the outer query and the subquery. You would phrase it as:
select s.*
from stud_cdl_comp_test s
inner join (
select student_id, licence, min(exam_date) as minexamdate
from stud_cdl_comp_test as scct
group by stud_id, licence
) s1 on s1.student_id = s.student_id and s1.license = s.license and s1.minexamdate = s.date
I have no idea what stud and agent_profile are, so I removed the from the query.
That said, this is not the method I would recommend - a simple and efficient option is to filter with a subquery:
select *
from stud_cdl_comp_test s
where s.exam_date = (
select min(s1.exam_date)
from stud_cdl_comp_test s1
where s1.student_id = s.student_id and s1.license = s.license
)
This can take advantage of an index on (student_id, license, exam_date).
Alternatively, you can use row_number(), available in MySL 8.0:
select *
from (
select s.*,
row_number() over(partition by student_id, licence order by exam_date) rn
from stud_cdl_comp_test s
) s
where rn = 1
Thinking that you are grouping by student_id in this case is almost incorrect in this case. What are actually grouping by is student + license. Let's call this key combination individual_license.
Here's what the solution will look like:
SELECT
st.id,
st.stud_id,
st.exam_date,
st.license,
st.result
FROM stud_cdl_comp_test AS st
INNER JOIN
(SELECT
MIN(exam_date) AS min_date,
st_inner.student_id,
st_inner.license
FROM stud_cdl_comp_test AS st_inner
GROUP BY st_inner.student_id, st_inner.license
) grouped_inner
ON grouped_inner.student_id = st.student_id
AND grouped_inner.license = st.license
AND grouped_inner.min_date = st.exam_date;
This should work.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a table as shown below
id | t_id | u_id
---+------+------
1 | 2 | 2
2 | 1 | 2
3 | 1 | 1
4 | 2 | 2
5 | 1 | 1
I am trying to get all t_id with u_id of 2 but once without the t_id ever having a u_id of 1 in the history of the whole table.
I tried
SELECT
C_Name, count(*) as count
FROM tenter
WHERE C_Date = '20200127' AND L_TID = '2';
But this gives me the record of all L_TID = 2 and does not filter out those with previous record of L_tid = 1.
Expected result: get all U_ID without the previous history of L_TID = 1, it should get only those without ever having L_tid =1.
Thanks in advance.
One method is aggregation and a having clause:
select t_id
from tenter t
group by t_id
having sum(u_id = 2) > 0 and -- has "2"
sum(u_id = 1) = 0; -- does not have "1"
If you have another table of t values, then exists/not exists might be more efficient:
select t.t_id
from t
where exists (select 1 from tenter tt where tt.t_id = t.t_id and tt.u_id = 2) and
not exists (select 1 from tenter tt where tt.t_id = t.t_id and tt.u_id = 1);
I think you want not exists:
select t.*
from tenter t
where
u_id = 2
and not exists (
select 1 from tenter t1 where t1.t_id = t.t_id and t1.u_id = 1
)
You can also use aggregation, if you just want a list of t_ids. If 1 and 2 are the only possible values, you can just do:
select t_id
from tenter t
group by t_id
having min(u_id) = 2
If there are other possible values:
having max(u_id = 1) = 0 and max(u_id = 2) = 1
I have searched this site and others but cannot find any help with this problem. Maybe I am making this more difficult than necessary.
I have two tables as follows. I want to return all the information for each item but only the most recent data and include data from both tables
table 1: serviceRequestSubmission
sid customerID
1001 11111
1002 22222
1003 33333
1004 44444
1005 55555
table 2: serviceRequestHistory
historyID requestID statusUpdate
1 1001 Assigned
2 1002 Assigned
3 1003 Pending
4 1004 Delayed
5 1002 Pending
6 1002 Closed
I want to return:
sidID historyID statusUpdate
1001 1 Assigned
1002 6 Closed
1003 3 Pending
1004 4 Delayed
1005 - Submitted
I have tried the following code but it returns all the rows of data but I only want the most recent/highest historyID.
SELECT serviceRequestSubmissions.*, serviceRequestHistory.*
FROM serviceRequestSubmissions
LEFT JOIN serviceRequestHistory ON serviceRequestSubmissions.sid = serviceRequestHistory.requestID
ORDER BY serviceRequestSubmissions.sid DESC
Any help would be appreciated.
Thank you!
SELECT serviceRequestSubmissions.*, serviceRequestHistory.*
FROM serviceRequestSubmissions
LEFT JOIN serviceRequestHistory
ON serviceRequestSubmissions.sid = serviceRequestHistory.requestID
AND historyID IN (
SELECT max(historyID)
FROM serviceRequestHistory
GROUP BY requestID
)
ORDER BY serviceRequestSubmissions.sid DESC
EDIT:
Only closed:
SELECT serviceRequestSubmissions.*, serviceRequestHistory.*
FROM serviceRequestSubmissions
JOIN serviceRequestHistory
ON serviceRequestSubmissions.sid = serviceRequestHistory.requestID
AND historyID IN (
SELECT max(historyID)
FROM serviceRequestHistory
WHERE statusUpdate = 'Closed'
GROUP BY requestID
)
ORDER BY serviceRequestSubmissions.sid DESC
Add a LIMIT clause at the end of the query:
LIMIT 2
You can use TIMESTAMP or id in your database and fetch record which has greatest TIMESTAMP or id value or with descending TIMESTAMP or id order by LIMIT clause
This is a common problem of type greatest-n-per-group. I think this is the best way to solve it:
SELECT
s.sid sidID,
IFNULL(h1.historyID,'-') historyID,
IFNULL(h1.statusUpdate,'Submitted') statusUpdate
FROM
serviceRequestSubmissions s
LEFT JOIN serviceRequestHistory h1 ON ( s.sid = h1.requestID )
LEFT JOIN serviceRequestHistory h2 ON ( s.sid = h2.requestID AND ( h1.historyID < h2.historyID OR h1.historyID = h2.historyID AND h1.requestID < h2.requestID ) )
WHERE
h2.requestID IS NULL
ORDER BY
s.sid
This is how it works: given a row of the table serviceRequestHistory, there shouldn't be any other row with the same requestID and a greater historyID (the conditions after the OR is to solve the ties). This kind of solution is usually better than using sub-selects.
I've got 3 tables - entryrecord, employee and employee_entryrecord (linking table).
The query I'd like is for it to return the most recent (max time) inout record for each employee.
employee
id employee
1 John
2 Tom
entryrecord
id created_date inout
1 2016-07-22 16:01:38 1
2 2016-07-22 16:03:22 1
3 2016-07-22 16:05:22 2
4 2016-07-22 16:07:22 2
5 2016-07-22 16:09:22 1
I'd like the follow output
created_date employee inout entryrecordid
2016-07-22 16:09:22 John 1 5
2016-07-22 16:05:22 Tom 2 3
However, in the sqlfiddle below you can see it does not return the correct inout and entryrecordid values.
I've created a sqlfiddle to view what I've done.
SQL Fiddle
Any help would be great.
Thanks.
Please give it a try:
SELECT
finalALias.created_date,
E.employee,
finalALias.inout,
finalALias.id AS entryrecordid
FROM employee E
INNER JOIN
(
SELECT
*
FROM entryrecord entryR
INNER JOIN
(
SELECT
EER.employeeid,
MAX(created_date) max_time
FROM entryrecord ER
INNER JOIN employee_entryrecord EER ON ER.id = EER.entryrecordid
GROUP BY EER.employeeid
) t
ON t.max_time=entryR.created_date
) AS finalALias
ON E.id = finalALias.employeeid
ORDER BY finalALias.created_date DESC;
WORKING DEMO
Just a gentle reminder:
E -> employee
ER -> entryrecord
ERR -> employee_entryrecord
The problem is that grouping happens before ordering. You will have to do a sub query. You always want to try and keep your sub queries to a minimum as they put a heavy toll on the SQL server.
I changed your LEFT JOINS to INNER JOINS because it looked like you wanted to only get employees that were in the other tables.
SELECT
entryrecord.created_date,
employee.employee,
entryrecord.inout,
entryrecord.id
FROM
entryrecord
INNER JOIN
employee_entryrecord ON entryrecord.id = employee_entryrecord.entryrecordid
INNER JOIN
employee ON employee_entryrecord.employeeid = employee.id
WHERE
entryrecord.inout in (1,2)
AND entryrecord.id = (
SELECT er2.id
FROM employee_entryrecord eer2, entryrecord er2
WHERE eer2.employeeid = employee.id
AND er2.id = eer2.entryrecordid
ORDER BY er2.created_date DESC LIMIT 1
)
I have two calls this "tipo_hh" and "tipo_hh_historial".
I need to make a join between the two tables, where "id" is the same in both tables.
But I need that for each "id" in the table "tipo_hh" select the "valor" on the table "tipo_hh_historial" with the condition that is the record with "fecha_cambio" and "hora_cambio" maxima.
"id" is primary key and auto increment in the table "tipo_hh"
Something like this.
This is the table "tipo_hh"
id nombre
1 Reefer
2 Lavados
3 Dry
4 Despacho
This is the table "tipo_hh_historial"
id valor fecha_cambio hora_cambio
1 1.50 27/06/2013 19:15:05
1 5.50 27/06/2013 19:19:32
1 5.50 27/06/2013 19:20:06
1 2.50 27/06/2013 21:03:30
2 4.66 27/06/2013 19:15:17
2 3.00 27/06/2013 19:20:22
3 5.00 27/06/2013 19:20:32
4 1.50 27/06/2013 19:20:50
And I need this:
id nombre valor
1 Reefer 2.50
2 Lavados 3.00
3 Dry 5.00
4 Despacho 1.50
Using a sub query to get the max date / time for the historical record for each id, and using that to get the rest of the latest historical record:-
SELECT tipo_hh.id, tipo_hh.nombre, tipo_hh_historial.valor
FROM tipo_hh
INNER JOIN
(
SELECT id, MAX(STR_TO_DATE(CONCAT(fecha_cambio, hora_cambio), '%d/%m/%Y%k:%i:%s')) AS MaxDateTime
FROM tipo_hh_historial
GROUP BY id
) Sub1
ON tipo_hh.id = Sub1.id
INNER JOIN tipo_hh_historial
ON tipo_hh_historial.id = Sub1.id
AND STR_TO_DATE(CONCAT(fecha_cambio, hora_cambio), '%d/%m/%Y%k:%i:%s') = Sub1.MaxDateTime
SQL Fiddle:-
http://www.sqlfiddle.com/#!2/68baa/2
First of all you should use proper data types for your columns like for date there should a column of type data same as for the time column in you sample data set you have date formatted as '%d/%m/%Y' id this could be change to standard format '%Y-%m-%d' this will be good to so the below query is for proper types for the columns
SELECT t.* ,new_tipo_hh_historial.`valor`
FROM tipo_hh_new t
JOIN (
SELECT th.*
FROM tipo_hh_historial_new th
JOIN (
SELECT id,valor,
MAX(fecha_cambio ) fecha_cambio
,MAX(hora_cambio) hora_cambio
FROM `tipo_hh_historial_new`
GROUP BY id
) thh
ON (
th.`id` =thh.`id`
AND th.fecha_cambio=thh.`fecha_cambio`
AND th.hora_cambio = thh.`hora_cambio`
)
) new_tipo_hh_historial
USING (id)
Fiddle Demo
And for in case you have date and time stored as string then you need to format them as real types you can use below query but not recommended
SELECT t.* ,new_tipo_hh_historial.`valor`
FROM tipo_hh t
JOIN (
SELECT th.*
FROM tipo_hh_historial th
JOIN (
SELECT id,valor,
MAX(STR_TO_DATE(fecha_cambio , '%d/%m/%Y')) fecha_cambio
,MAX(TIME_FORMAT(hora_cambio,'%H:%i:%s')) hora_cambio
FROM `tipo_hh_historial`
GROUP BY id
) thh
ON (
th.`id` =thh.`id`
AND STR_TO_DATE(th.fecha_cambio , '%d/%m/%Y')=thh.`fecha_cambio`
AND TIME_FORMAT(th.hora_cambio,'%H:%i:%s') = thh.`hora_cambio`
)
) new_tipo_hh_historial
USING (id)
Fiddle Demo
Your problem seems like the greatest-n-per-group problem so you can first get the maxima from your table tipo_hh_historial maxima of fecha_cambio and hora_cambio and need to self join with multiple conditions to get the maximums like i.e
ON (
th.`id` =thh.`id`
AND th.fecha_cambio=thh.`fecha_cambio`
AND th.hora_cambio = thh.`hora_cambio`
)
and then join with your first table to get the expected results
Edit: the problem spotted by #Kickstart he already answered so i will provide the another way to overcome.There should be single field to store the date and time for the record like for fecha_cambio DATETIME so there will no chance to miss the id and get the correct maxima for date and time.See below updated query
SELECT t.* ,new_tipo_hh_historial.`valor`
FROM tipo_hh_new t
JOIN (
SELECT th.*
FROM tipo_hh_historial_alter th
JOIN (
SELECT id,valor,
MAX(fecha_cambio ) fecha_cambio
FROM `tipo_hh_historial_alter`
GROUP BY id
) thh
ON (
th.`id` =thh.`id`
AND th.fecha_cambio=thh.`fecha_cambio`
)
) new_tipo_hh_historial
USING (id)
Updated fiddle demo
try this:
SELECT A.id, B.nombre, A.valor, MAX(A.hora_cambio) AS hora_cambio_time
FROM tipo_hh_historial AS A
INNER JOIN tipo_hh AS B
ON(A.id = B.id)
GROUP BY A.id
SELECT tipo_hh.id, tipo_hh.nombre, tipo_hh_historial.valor
FROM tipo_hh INNER JOIN tipo_hh_historial
ON tipo.id = tipo_hh_historial.id AS
group by tipo_hh_historial.id
Having max(tipo_hh_historial.hora_cambio);