I have a patients database with multiple tables, and I need to join specific columns (pre-processed) from different tables in a results table. Here's how I do it:
SELECT d_patients.subject_id, icustay_detail.subject_icustay_seq,
icustay_detail.icustay_id,
icustay_detail.icustay_admit_age, d_patients.sex,
icustay_detail.icustay_los/(60*24) los,
icustay_detail.weight_first/POWER(icustay_detail.height/100,2) bmi,
COALESCE( a.additives, 0 ) as additives,
COALESCE( p.procedureevents, 0 ) as procedureevents,
COALESCE( d.duration, 0 ) as duration,
COALESCE ( m.medications,0 ) as medications
FROM icustay_detail
INNER JOIN d_patients
ON icustay_detail.subject_id = d_patients.subject_id
LEFT JOIN
( SELECT subject_id, count(*) as additives
FROM additives
GROUP BY subject_id
) a
ON icustay_detail.subject_id = a.subject_id
LEFT JOIN
( SELECT subject_id, count(*) as procedureevents
FROM procedureevents
GROUP BY subject_id
) p
ON icustay_detail.subject_id = p.subject_id
LEFT JOIN
( SELECT subject_id, SUM(duration) as duration
FROM a_meddurations
GROUP BY subject_id
) d
ON icustay_detail.subject_id = d.subject_id
LEFT JOIN
( SELECT icustay_id, COUNT(DISTINCT solutionid)
AS medications
FROM medevents
GROUP BY icustay_id
) m
ON icustay_detail.icustay_id = m.icustay_id;
Up until here, the code works fine and the resulting table is the following
subject_id | subject_icustay_seq | icustay_id | icustay_admit_age | sex | los | bmi | additives | procedureevents | duration | medications
------------+---------------------+------------+-------------------+-----+----------------------+------------------+-----------+-----------------+----------+-------------
3 | 1 | 4 | 76.52892 | M | 6.06458333333333 | 30.18767669244 | 10 | 6 | 59145 | 2
12 | 1 | 13 | 72.36841 | M | 7.63472222222222 | | 3 | 10 | 15092 | 2
21 | 1 | 23 | 87.43771 | M | 5.90208333333333 | 21.3569005167836 | 7 | 15 | 0 | 1
21 | 2 | 24 | 87.82761 | M | 8.36527777777778 | | 7 | 15 | 0 | 1
26 | 1 | 29 | 72.00637 | M | 2.47569444444444 | | 0 | 2 | 0 | 0
31 | 1 | 34 | 72.26327 | M | 7.93819444444444 | 22.12581585657 | 6 | 6 | 18316 | 2
37 | 1 | 41 | 68.93134 | M | 1.13958333333333 | | 0 | 2 | 0 | 0
56 | 1 | 62 | 90.6427 | F | 1.84930555555556 | | 3 | 2 | 0 | 0
61 | 1 | 67 | 54.72569 | M | 2.55972222222222 | 18.168292503669 | 1 | 15 | 0 | 0
61 | 2 | 68 | 55.249 | M | 2.04791666666667 | | 1 | 15 | 0 | 1
61 | 3 | 69 | 55.26185 | M | 0.00277777777777778 | | 1 | 15 | 0 | 0
67 | 1 | 76 | 73.48396 | M | 0.214583333333333 | 23.8462015385569 | 2 | 1 | 160 | 1
78 | 1 | 89 | 48.62681 | M | 1.48958333333333 | | 1 | 1 | 2125 | 1
83 | 1 | 94 | 65.54958 | F | 2.30902777777778 | | 0 | 3 | 0 | 0
94 | 1 | 107 | 74.43468 | M | 1.09861111111111 | | 13 | 12 | 0 | 2
94 | 2 | 108 | 74.95603 | M | 22.8979166666667 | | 13 | 12 | 0 | 2
105 | 1 | 121 | 35.33793 | F | 4.99722222222222 | | 2 | 0 | 0 | 0
105 | 2 | 122 | 35.4088 | F | 1.61944444444444 | | 2 | 0 | 0 | 0
106 | 1 | 123 | 35.6095 | M | 6.1625 | 22.4312567927803 | 5 | 1 | 0 | 3
112 | 1 | 136 | 91.96166 | M | 0.840277777777778 | | 5 | 8 | 0 | 0
112 | 2 | 137 | 94.25 | M | 1.13888888888889 | | 5 | 8 | 0 | 2
The problem is when I try to add another column (abnormal) from another table (labevents), which is adding this part:
LEFT JOIN
( SELECT subject_id, round((COUNT(flag) * 100)::numeric / COUNT(*), 2) as abnormal
FROM labevents
GROUP BY subject_id
) ab
ON icustay_detail.subject_id = ab.subject_id
The resulting code is the following:
SELECT d_patients.subject_id, icustay_detail.subject_icustay_seq,
icustay_detail.icustay_id,
icustay_detail.icustay_admit_age, d_patients.sex,
icustay_detail.icustay_los/(60*24) los,
icustay_detail.weight_first/POWER(icustay_detail.height/100,2) bmi,
COALESCE( a.additives, 0 ) as additives,
COALESCE( p.procedureevents, 0 ) as procedureevents,
COALESCE( d.duration, 0 ) as duration,
COALESCE( ab.abnormal, 0 ) as abnormal,
COALESCE( m.medications,0 ) as medications
FROM icustay_detail
INNER JOIN d_patients
ON icustay_detail.subject_id = d_patients.subject_id
LEFT JOIN
( SELECT subject_id, count(*) as additives
FROM additives
GROUP BY subject_id
) a
ON icustay_detail.subject_id = a.subject_id
LEFT JOIN
( SELECT subject_id, count(*) as procedureevents
FROM procedureevents
GROUP BY subject_id
) p
ON icustay_detail.subject_id = p.subject_id
LEFT JOIN
( SELECT subject_id, SUM(duration) as duration
FROM a_meddurations
GROUP BY subject_id
) d
ON icustay_detail.subject_id = d.subject_id
LEFT JOIN
( SELECT subject_id, round((COUNT(flag) * 100)::numeric / COUNT(*), 2) as abnormal
FROM labevents
GROUP BY subject_id
) ab
ON icustay_detail.subject_id = ab.subject_id
LEFT JOIN
( SELECT icustay_id, COUNT(DISTINCT solutionid)
AS medications
FROM medevents
GROUP BY icustay_id
) m
ON icustay_detail.icustay_id = m.icustay_id;
What happens is that the patient rows with 0 value in the "medications" column are removed, and I don't know why. The resulting table is this one:
subject_id | subject_icustay_seq | icustay_id | icustay_admit_age | sex | los | bmi | additives | procedureevents | duration | abnormal | medications
------------+---------------------+------------+-------------------+-----+----------------------+------------------+-----------+-----------------+----------+----------+-------------
3 | 1 | 4 | 76.52892 | M | 6.06458333333333 | 30.18767669244 | 10 | 6 | 59145 | 23.15 | 2
12 | 1 | 13 | 72.36841 | M | 7.63472222222222 | | 3 | 10 | 15092 | 41.85 | 2
21 | 1 | 23 | 87.43771 | M | 5.90208333333333 | 21.3569005167836 | 7 | 15 | 0 | 43.74 | 1
21 | 2 | 24 | 87.82761 | M | 8.36527777777778 | | 7 | 15 | 0 | 43.74 | 1
31 | 1 | 34 | 72.26327 | M | 7.93819444444444 | 22.12581585657 | 6 | 6 | 18316 | 26.69 | 2
61 | 2 | 68 | 55.249 | M | 2.04791666666667 | | 1 | 15 | 0 | 41.63 | 1
67 | 1 | 76 | 73.48396 | M | 0.214583333333333 | 23.8462015385569 | 2 | 1 | 160 | 29.73 | 1
78 | 1 | 89 | 48.62681 | M | 1.48958333333333 | | 1 | 1 | 2125 | 35.75 | 1
94 | 1 | 107 | 74.43468 | M | 1.09861111111111 | | 13 | 12 | 0 | 34.10 | 2
94 | 2 | 108 | 74.95603 | M | 22.8979166666667 | | 13 | 12 | 0 | 34.10 | 2
106 | 1 | 123 | 35.6095 | M | 6.1625 | 22.4312567927803 | 5 | 1 | 0 | 37.67 | 3
112 | 2 | 137 | 94.25 | M | 1.13888888888889 | | 5 | 8 | 0 | 33.67 | 2
117 | 1 | 143 | 49.2842 | F | 1.32013888888889 | | 14 | 15 | 42785 | 47.76 | 1
117 | 2 | 144 | 49.89653 | F | 13.2493055555556 | 40.9070642360035 | 14 | 15 | 42785 | 47.76 | 3
124 | 1 | 151 | 69.63652 | M | 3.91111111111111 | 22.1382505356903 | 7 | 8 | 8560 | 24.24 | 1
124 | 2 | 152 | 71.07388 | M | 7.18958333333333 | | 7 | 8 | 8560 | 24.24 | 1
146 | 1 | 181 | 85.56421 | M | 7.57013888888889 | 34.7959879593229 | 11 | 9 | 32648 | 35.88 | 2
148 | 1 | 183 | 78.1597 | F | 15.2958333333333 | | 7 | 7 | 2826493 | 36.68 | 3
150 | 1 | 185 | 37.82158 | F | 2.26180555555556 | 14.2542487150986 | 1 | 4 | 3083 | 23.10 | 1
157 | 2 | 195 | 80.53706 | M | 4.11944444444444 | | 6 | 11 | 0 | 33.84 | 2
Please let me know if you need the specific content of the tables to try to understand the error. Thank you so much in advance.
Best,
Guille
Related
Edit
Please consider this before marking as duplicate
The common CTE or repeated joins or similar solutions does not fully satisfy the premise of the problem. Those solutions work for one and only one root (product) while the question at hand, asks for all roots within a table or query to be traversed and flattened, without a loop.
Problem Definition
I have three tables that define the characteristics of some products:
specifications
+----|------------------|----------|--------+
| id | name | type | status |
|----|------------------|----------|--------|
| 1 | height | float | 0 |
| 2 | width | float | 0 |
| 3 | length | float | 0 |
| 4 | weight | float | 0 |
| 5 | colour | int | 0 |
| 6 | material | int | 0 |
| 7 | manufacturer | int | 0 |
| 8 | durability | float | 0 |
| 9 | battery_type | int | 0 |
| 10 | battery_capacity | float | 0 |
| 11 | connectivity | set<int> | 0 |
| 12 | page | int | 0 |
| 13 | name | string | 0 |
| 14 | description | string | 0 |
+----|------------------|----------|--------+
groups
+----|-------------------|--------+
| id | name | status |
|----|-------------------|--------|
| 1 | cellphone | 0 |
| 2 | notebook | 0 |
| 3 | portable | 0 |
| 4 | workstation | 0 |
| 5 | pc | 0 |
| 6 | computer | 0 |
| 7 | electronic_device | 0 |
| 8 | book | 0 |
| 9 | sizeable | 0 |
| 10 | volumable | 0 |
| 11 | general | 0 |
+----|-------------------|--------+
specification_groups
+----|----------|------------------|--------+
| id | group_id | specification_id | status |
|----|----------|------------------|--------|
| 1 | 11 | 13 | 0 |
| 2 | 11 | 14 | 0 |
| 3 | 11 | 5 | 0 |
| 4 | 10 | 1 | 0 |
| 5 | 9 | 2 | 0 |
| 6 | 9 | 3 | 0 |
| 7 | 8 | 12 | 0 |
| 8 | 3 | 6 | 0 |
| 9 | 3 | 9 | 0 |
| 10 | 3 | 10 | 0 |
| 11 | 7 | 7 | 0 |
| 12 | 7 | 11 | 0 |
+----|----------|------------------|--------+
group_groups
+----|----------|--------------------|--------+
| id | group_id | group_reference_id | status |
|----|----------|--------------------|--------|
| 1 | 3 | 1 | 0 |
| 2 | 3 | 2 | 0 |
| 3 | 3 | 8 | 0 |
| 4 | 6 | 4 | 0 |
| 5 | 6 | 5 | 0 |
| 6 | 7 | 1 | 0 |
| 7 | 7 | 2 | 0 |
| 8 | 7 | 4 | 0 |
| 9 | 7 | 5 | 0 |
| 10 | 9 | 7 | 0 |
| 11 | 9 | 8 | 0 |
| 12 | 10 | 7 | 0 |
| 12 | 11 | 7 | 0 |
| 12 | 11 | 8 | 0 |
+----|----------|--------------------|--------+
product_groups
+----|--------|-------|--------+
| id | name | group | status |
|----|--------|-------|--------|
| 1 | phone1 | 1 | 0 |
| 2 | book1 | 8 | 0 |
+----|--------|-------|--------+
Ideally, I want to get all specification attributes for a product which the status along all tree-lines would be 0, but just to know what groups does a product is in is acceptable.
A result may look like this:
result
+---------|-------------|--------------|-------------------|----------|--------+
| row_num | product_id | product_name | product_group | group_id | status |
|---------|-------------|--------------|-------------------|----------|--------|
| 1 | 1 | phone1 | cellphone | 1 | 0 |
| 2 | 1 | phone1 | portable | 3 | 0 |
| 3 | 1 | phone1 | electronic_device | 7 | 0 |
| 4 | 1 | phone1 | sizable | 9 | 0 |
| 5 | 1 | phone1 | volumable | 10 | 0 |
| 6 | 1 | phone1 | general | 11 | 0 |
| 7 | 2 | book1 | book | 8 | 0 |
| 8 | 2 | book1 | portable | 3 | 0 |
| 9 | 2 | book1 | sizable | 9 | 0 |
| 10 | 2 | book1 | general | 11 | 0 |
+---------|-------------|--------------|-------------------|----------|--------+
Here's the answer if anyone else wants to do the same. The trick was to use the non-recursive initial selection parameters as constants in the recursive one:
with recursive
q as (
select * from product_groups as pg where ur.`status` = 0
)
, ancestors as (
(
select q.id as `product_id`, q.product_name as `product_name`, gg.group_id as `group_id`, gg.group_reference_id as `group_reference_id`
from group_groups as gg
join q on gg.group_id = q.group_id
where gg.`status` = 0
)
union
(
select q.id as `product_id`, q.product_name as `product_name`, null as `group_id`, q.group_id as `group_reference_id`
from q
)
union
(
select a.id as `product_id`, a.product_name as `product_name`, gg.group_id as `group_id`, gg.group_reference_id as `group_reference_id`
from group_groups as gg, ancestors as a
where gg.group_id = a.group_reference_id and gg.`status` = 0
)
)
select distinct
t.id as `product_id`, t.`group_id` as `group_id`, t.specification_id as `specification_id`, t.product_name as `product_name`, t.group_name as `group_name`, s.name as `specification_name`
from
(
select a.product_id, a.group_reference_id as `group_id`, sg.specification_id as `specification_id`, a.product_name, g.name as `group_name`
from ancestors as a
right join specification_groups as sg on a.group_reference_id = sg.group_id
where a.product_id is not null and sg.`status` = 0
) as t
join specifications as s on t.specification_id = s.id
order by product_id asc, group_id, asc, specification_id asc
;
I am trying to create a trigger in MySQL database. I have a table (myData) with 3 columns. Date, Values, and Status. What I am trying to achieve is, when a new value comes, if it is higher than the last value, It should insert 1 in the Status column. If it is less than the last value, It should insert 0 in the status column. I couldn't find a logic to do it. Any suggestions, please?
BEGIN
IF new.Values > // what should be here?
THEN
INSERT INTO //
END
Instead consider the following:
SELECT * FROM my_table;
+----+-------+
| id | value |
+----+-------+
| 1 | 2 |
| 2 | 12 |
| 3 | 13 |
| 4 | 9 |
| 5 | 7 |
| 6 | 6 |
| 7 | 8 |
| 8 | 3 |
| 9 | 10 |
| 10 | 1 |
| 11 | 18 |
| 12 | 4 |
| 13 | 6 |
| 14 | 0 |
| 15 | 2 |
| 16 | 8 |
| 17 | 14 |
| 18 | 7 |
| 19 | 15 |
| 20 | 11 |
| 21 | 12 |
| 22 | 7 |
| 23 | 20 |
| 24 | 17 |
| 25 | 8 |
| 26 | 6 |
| 27 | 6 |
| 28 | 12 |
| 29 | 3 |
| 30 | 18 |
| 31 | 1 |
| 32 | 12 |
+----+-------+
SELECT a.*
, b.value >= a.value n
FROM my_table a
LEFT
JOIN
( SELECT x.*
, MIN(y.id) next
FROM my_table x
LEFT
JOIN my_table y
ON y.id > x.id
GROUP
BY x.id
) b
ON b.next = a.id;
+----+-------+------+
| id | value | n |
+----+-------+------+
| 1 | 2 | NULL |
| 2 | 12 | 0 |
| 3 | 13 | 0 |
| 4 | 9 | 1 |
| 5 | 7 | 1 |
| 6 | 6 | 1 |
| 7 | 8 | 0 |
| 8 | 3 | 1 |
| 9 | 10 | 0 |
| 10 | 1 | 1 |
| 11 | 18 | 0 |
| 12 | 4 | 1 |
| 13 | 6 | 0 |
| 14 | 0 | 1 |
| 15 | 2 | 0 |
| 16 | 8 | 0 |
| 17 | 14 | 0 |
| 18 | 7 | 1 |
| 19 | 15 | 0 |
| 20 | 11 | 1 |
| 21 | 12 | 0 |
| 22 | 7 | 1 |
| 23 | 20 | 0 |
| 24 | 17 | 1 |
| 25 | 8 | 1 |
| 26 | 6 | 1 |
| 27 | 6 | 1 |
| 28 | 12 | 0 |
| 29 | 3 | 1 |
| 30 | 18 | 0 |
| 31 | 1 | 1 |
| 32 | 12 | 0 |
+----+-------+------+
If all you want is the rows where n=1, then the query is actually even simpler...
SELECT a.*
FROM my_table a
JOIN
( SELECT x.*
, MIN(y.id) next
FROM my_table x
LEFT
JOIN my_table y
ON y.id > x.id
GROUP
BY x.id
) b
ON b.next = a.id
AND b.value >= a.value;
+----+-------+
| id | value |
+----+-------+
| 4 | 9 |
| 5 | 7 |
| 6 | 6 |
| 8 | 3 |
| 10 | 1 |
| 12 | 4 |
| 14 | 0 |
| 18 | 7 |
| 20 | 11 |
| 22 | 7 |
| 24 | 17 |
| 25 | 8 |
| 26 | 6 |
| 27 | 6 |
| 29 | 3 |
| 31 | 1 |
+----+-------+
I have these tables ;
Mysql Tables[Click Here]
attendance table
+-----+------------+--------+---------+--+
| id | atdnc_date | emp_id | isleave | |
+-----+------------+--------+---------+--+
| 138 | 2018-11-22 | 1024 | 1 | |
| 133 | 2018-11-21 | 6 | 0 | |
| 130 | 2018-11-20 | 6 | 0 | |
| 129 | 2018-11-20 | 71 | 1 | |
| 126 | 2018-11-19 | 817 | 0 | |
| 122 | 2018-11-18 | 355 | 0 | |
| 123 | 2018-11-18 | 6 | 0 | |
| 190 | 2018-11-17 | 355 | 1 | |
| 119 | 2018-11-17 | 817 | 0 | |
| 117 | 2018-11-17 | 6 | 0 | |
| 116 | 2018-11-17 | 71 | 0 | |
| 113 | 2018-11-16 | 817 | 0 | |
+-----+------------+--------+---------+--+
driver table
+-----+-----------+-------------+--+
| id | driver_id | driver_lice | |
+-----+-----------+-------------+--+
| 131 | 817 | B67408 | |
| 132 | 450 | B548093 | |
| 133 | 6 | B1394007 | |
| 134 | 355 | B772739 | |
| 135 | 1024 | B204085 | |
| 136 | 71 | B2442775 | |
| 137 | 88881 | B2056537 | |
| 138 | 729 | B8265 | |
| 139 | 600 | B393570 | |
| 140 | 748 | B2228230 | |
+-----+-----------+-------------+--+
vehicle table
+-----+---------------+-----------+--+
| id | vehicle_id | driver_id | |
+-----+---------------+-----------+--+
| 137 | VH000137 | 817 | |
| 138 | VH000138 | 817 | |
| 139 | VH000139 | 600 | |
| 140 | VH000140 | 1024 | |
| 141 | VH000141 | 450 | |
| 142 | VH000142 | 600 | |
| 143 | VH000143 | 729 | |
| 144 | VH000144 | 817 | |
+-----+---------------+-----------+--+
vehicle_status table
+---------------+----------+----------------+--+
| vehicle_id | order_id | current_status | |
+---------------+----------+----------------+--+
| VH000137 | OR000130 | completed | |
| VH000138 | OR000131 | arrived_to_sup | |
| VH000139 | OR000132 | completed | |
| VH000140 | OR000133 | cancelled | |
| VH000141 | OR000134 | completed | |
| VH000142 | OR000135 | arrived_to_sup | |
| VH000143 | OR000136 | arrived_to_sup | |
| VH000144 | OR000137 | completed | |
+---------------+----------+----------------+--+
And i want get list of all drivers that ,
attendance.atdnc_date <> '2018-11-17' AND attendance.isleave<>1
OR that attendance row is null according to driver
AND
vehicle_status.current_status = 'cancelled' OR vehicle_status.current_status = 'completed'
OR, OR that vehicle_status row is null according to driver
here i tried queries:
1)
SELECT * FROM
(SELECT driver.* FROM driver LEFT JOIN (SELECT vehicle.* FROM vehicle_status INNER JOIN vehicle ON vehicle_status.vehicle_id=vehicle.vehicle_id WHERE current_status <> 'completed' AND current_status <> 'cancelled') k
ON driver.driver_id=k.driver_id INNER JOIN(SELECT driver.driver_id FROM driver LEFT JOIN (SELECT emp_id FROM `attendance` WHERE isleave=1 AND atdnc_date='2018-11-17') as x ON x.emp_id=driver.driver_id WHERE x.emp_id IS NULL ) d ON driver.driver_id=d.driver_id ) as x
2)
SELECT * FROM driver
LEFT JOIN vehicle ON driver.driver_id=vehicle.driver_id
LEFT JOIN vehicle_status ON vehicle.vehicle_id=vehicle_status.vehicle_id
LEFT JOIN attendance ON driver.driver_id=attendance.emp_id WHERE (vehicle_status.current_status ="completed" OR vehicle_status.current_status ="cancelled" OR vehicle_status.current_status IS NULL)
AND ((attendance.atdnc_date = '2018-11-17' AND attendance.isleave = 0) OR (attendance.atdnc_date IS NULL) ) GROUP BY driver.driver_id
3)
SELECT * FROM (SELECT driver.* FROM driver LEFT JOIN (SELECT vehicle.* FROM vehicle_status INNER JOIN vehicle ON vehicle_status.vehicle_id=vehicle.vehicle_id WHERE current_status <> 'completed' AND current_status <> 'cancelled') k ON driver.driver_id=k.driver_id WHERE k.driver_id IS NULL) x
INNER JOIN (SELECT driver.* FROM driver LEFT JOIN attendance ON driver.driver_id=attendance.emp_id WHERE ((attendance.atdnc_date <> '2018-11-17' AND attendance.isleave <> 0) OR (attendance.atdnc_date IS NULL) )) b ON x.driver_id=b.driver_id
i think this working.. but can be slow when using with large set of data.
4)
select b.* FROM (SELECT driver.* FROM driver LEFT JOIN (SELECT vehicle.* FROM vehicle_status INNER JOIN vehicle ON vehicle_status.vehicle_id=vehicle.vehicle_id WHERE current_status <> 'completed' AND current_status <> 'cancelled') k
ON driver.driver_id=k.driver_id WHERE k.driver_id IS NULL) b
LEFT JOIN (SELECT driver.driver_id FROM attendance INNER JOIN driver ON attendance.emp_id=driver.driver_id WHERE attendance.atdnc_date='2018-11-17' AND attendance.isleave='1') k ON b.driver_id=k.driver_id
WHERE k.driver_id IS NULL AND status ='1'
these queries sometimes work. but when attendance, and vehicle_status have multiple rows with driver, these quires fail. and show multiple drivers or show drivers that not meet the conditions :(
expected result
+-----+-----------+-------------+--+
| id | driver_id | driver_lice | |
+-----+-----------+-------------+--+
| 132 | 450 | B548093 | |
| 133 | 6 | B1394007 | |
| 136 | 71 | B2442775 | |
| 137 | 88881 | B2056537 | |
| 138 | 729 | B8265 | |
| 140 | 748 | B2228230 | |
| 138 | 1024| B204085 | |
+-----+-----------+-------------+--+
Here is the table with some data
+-----+-------+--------+-----------+------------+-------+------------+---------------------+-------------------+
| id | level | userId | numOfSecs | numOfStars | score | mostRecent | creationTime | allLevelsFinished |
+-----+-------+--------+-----------+------------+-------+------------+---------------------+-------------------+
| 113 | 1 | 21 | 12 | 3 | 1000 | 1 | 2017-11-14 17:39:06 | 0 |
| 114 | 10 | 21 | 25 | 3 | 1000 | 1 | 2017-11-14 17:41:21 | 0 |
| 115 | 5 | 21 | 16 | 3 | 1000 | 1 | 2017-11-14 18:37:40 | 0 |
| 119 | 1 | 23 | 194 | 1 | 200 | 0 | 2017-11-15 13:21:50 | 0 |
| 120 | 1 | 23 | 121 | 1 | 444 | 0 | 2017-11-15 13:16:01 | 0 |
| 121 | 1 | 23 | 221 | 3 | 333 | 0 | 2017-11-15 18:14:48 | 0 |
| 122 | 1 | 23 | 343 | 2 | 555 | 0 | 2017-11-15 13:19:54 | 0 |
| 123 | 1 | 23 | 355 | 1 | 555 | 1 | 2017-11-15 13:21:19 | 0 |
| 124 | 2 | 23 | 333 | 1 | 333 | 0 | 2017-11-15 15:25:59 | 0 |
| 125 | 2 | 23 | 444 | 2 | 444 | 0 | 2017-11-15 15:26:26 | 0 |
| 126 | 2 | 23 | 222 | 2 | 2222 | 0 | 2017-11-15 15:26:59 | 0 |
| 127 | 2 | 23 | 44 | 1 | 444 | 1 | 2017-11-15 15:27:24 | 0 |
+-----+-------+--------+-----------+------------+-------+------------+---------------------+-------------------+
I'm aware that I could use
SELECT id, userId, numOfSecs, level, max(numOfStars)
WHERE userId=23
GROUP BY level
However, I'm interested in becoming more familiar with JOIN, even though JOIN is typically used with 2 or more tables. What I would like to do with my query is select all the rows where userId=23 and then do a second query on the results of the first query to find the max number of stars for each level listed. From the research I've done, a left inner join could do the job, but I'm having difficulty with aliases using a single table.
you can get the same using left join with same table but some tweaks in on clause to pick the highest numOfStars row
select a.*
from demo a
left join demo b
on a.userId = b.userId
and a.level = b.level
and case when a.numOfStars = b.numOfStars
then a.score < b.score
else a.numOfStars < b.numOfStars
end
where b.id is null
and a.userId = 23
Demo
Note i have added a case clause for a scenario if user id, level and numOfStars are equal then it will pick the row on basis of highest score
I have this working query that generate data the way i like it to happened but now i want it to add another clause statement that will get rows from tbl_loan_master that was not on the tbl_loanledger.
Example Data:
tbl_borrowers
------------------------------------------
| id | first_name | last_name | deleted |
| 1 | Joe | Smith | 0 |
| 2 | Lily | Mag | 0 |
| 3 | Zen | Green | 0 |
| 4 | Kim | Chan | 0 |
| 5 | Bob | Mac | 1 |
| 6 | Ben | Cork | 0 |
------------------------------------------
tbl_loan_master
----------------------------------------------------------------------
| id | borrowers_id | loan | date_created | due_date | deleted |
| 1 | 4 | 300 | 2016/04/28 | 2017/04/28 | 0 |
| 2 | 1 | 100 | 2016/05/05 | 2017/05/05 | 0 |
| 3 | 2 | 500 | 2016/06/08 | 2017/06/08 | 0 |
| 4 | 1 | 200 | 2016/06/13 | 2017/06/13 | 0 |
| 5 | 3 | 150 | 2016/06/15 | 2017/06/15 | 0 |
| 6 | 6 | 50 | 2016/06/16 | 2017/06/16 | 0 |
----------------------------------------------------------------------
tbl_loanledger
------------------------------------------------------------------------------
| id | borrowers_id | loanmaster_id | payment | balance| date_created | deleted
| 1 | 4 | 1 | 50 | 250 | 2016/05/28 | 0
| 2 | 1 | 2 | 20 | 80 | 2016/05/25 | 0
| 3 | 1 | 2 | 30 | 50 | 2016/06/01 | 0
| 4 | 2 | 3 | 100 | 400 | 2016/06/09 | 0
| 5 | 2 | 3 | 50 | 350 | 2016/06/10 | 0
| 6 | 3 | 4 | 50 | 150 | 2016/06/16 | 0
------------------------------------------------------------------------------
Here is the working query:
$query = "SELECT `tbl_borrowers`.* , `tbl_loanledger`.*, `tbl_loan_master`.*
FROM `tbl_borrowers`
LEFT JOIN `tbl_loanledger`
ON `tbl_borrowers`.id = `tbl_loanledger`.borrower_id
LEFT JOIN `tbl_loan_master`
ON `tbl_loan_master`.id = `tbl_loanledger`.loanmaster_id
WHERE `tbl_borrowers`.deleted = 0 AND `tbl_loanledger`.deleted = 0 AND MONTH ( `tbl_loanledger`.date_created) = MONTH(CURRENT_DATE)
GROUP BY `tbl_loanledger`.borrower_id
ORDER BY `tbl_borrowers`.last_name";
The expected result will output the borrowers with their last transaction on the current month (which is June) in loan ledger and also in loans accounts. Like Ben Cork which is not on the loan ledger, he is on the loan accounts but i want to output him on the result set. The deleted column means if it is 0 it indicates it is active if it is 0 it means it has been deleted.
Expected Result:
|First Name | Last Name | Due Date | Balance |
| Ben | Cork | 2017/06/16 | 50 |
| Joe | Smith | 2017/06/13 | 50 |
| Lily | Mag | 2017/06/08 | 350 |
| Zen | Green | 2017/06/15 | 150 |
Try following;)
select
tb.first_name, tb.last_name, coalesce(tlm.Loan, 0) as Loan, coalesce(t.`Amount Paid`, 0) as `Last Amount Paid`
from tbl_borrowers tb
left join tbl_loan_master tlm
on tb.id = tlm.borrowers_id
left join (
select t1.*
from tbl_loanledger t1
inner join (
select max(id) as id
from tbl_loanledger
group by borrowers_id, loanmaster_id
) t2 on t1.id = t2.id
) t
on tb.id = t.borrowers_id
and tlm.id = t.loanmaster_id
SQLFiddle DEMO HERE