When i add where in query it's now showing count 0 - mysql

I'm having a problem with a query is not showing COUNT 0 when i'm adding where clause.
I have two tables "Parking" & "Active_Parking". I want to get COUNT of active parkings per id_parking that datetime_out is >= then current time to compare with parking_space.
Parking
| id_parking | parking_name | parking_location | parking_space |
| -------------- | ------------ | ---------------- | ------------ |
| 1 | ABC | 1st street | 35 |
| 1 | ABC | 2nd street | 50 |
| 1 | ABC | 3rd street | 150 |
Active Parking
| id_active_parking | id_parking | car_plates | datetime_IN |
| ------------------- | ----------- | ---------- | -------------------- |
| 1 | 1 | 00-XXX-00 | 2018-12-16 14:00:00 |
| 2 | 1 | 00-XXX-00 | 2018-12-16 14:21:34 |
| 3 | 2 | 00-XXX-00 | 2018-12-16 21:35:00 |
| 4 | 2 | 00-XXX-00 | 2018-12-16 22:00:00 |
| datetime_OUT |
| -------------------- |
| 2018-12-16 15:00:00 |
| 2018-12-16 15:21:34 |
| 2018-12-16 22:35:00 |
| 2018-12-16 23:00:00 |
Query:
SELECT
p.id_parking,
p.parking_name,
p.parking_location,
p.parking_space,
COUNT(ap.id_parking) AS Active
FROM
parking p
LEFT JOIN active_parking ap
ON ap.id_parking = p.id_parking
WHERE
ap.datetime_OUT >= '2018-12-16 22:16:00'
GROUP BY p.id_parking
Query Result:
| id_parking | COUNT(ap.id_parking) |
| -------------- | -------------------- |
| 2 | 2 |
Is not showing id_parking 1 and 3 COUNT = 0

What is the reason to use LEFT JOIN in this case? Remove group by + count and check the result. I believe you should use INNER JOIN in this case. You can read about differences in many places, including wiki
If you really need all list of p.id_parking, you should move your WHERE clause to ON:
LEFT JOIN active_parking ap ON (
ap.id_parking = p.id_parking
AND ap.datetime_OUT >= '2018-12-16 22:16:00'
)
Then you should have proper count of active parkings.

Related

MySQL list all records in left table with Join

I have two tables, one includes vehicle data & other includes fuel data as follows:
tbl_vehicle
+------------+--------+
| vehicle_id | reg_no |
+------------+--------+
| 1 | ABC |
| 2 | DEF |
| 3 | GHI |
| 4 | JKA |
| 5 | LMN |
| 6 | OPQ |
+------------+--------+
tbl_direct_fuel
+---------+------------+----------+------------+
| fuel_id | vehicle_id | fuel_qty | date |
+---------+------------+----------+------------+
| 100 | 1 | 10 | 2019-10-01 |
| 101 | 1 | 12 | 2019-10-02 |
| 102 | 2 | 20 | 2019-10-03 |
| 103 | 3 | 15 | 2019-10-03 |
| 104 | 2 | 25 | 2019-10-04 |
+---------+------------+----------+------------+
I tried to get all records of left table with relevant records of right table. Used following Query.
select("reg_no,sum(fuel_qty) as total")
->from('tbl_direct_fuel')
->join('tbl_vehicle', 'tbl_direct_fuel.vehicle=tbl_vehicle.vehicle_id', 'left')
->group_by ('reg_no')
The above code shows only the following output.
+--------+----------+
| reg_no | total |
+--------+----------+
| ABC | 22 |
| DEF | 45 |
| GHI | 15 |
+--------+----------+
But I need all the vehicles with un-fueled vehicles as follows.
Desired output
+--------+----------+
| reg_no | total |
+--------+----------+
| ABC | 22 |
| DEF | 45 |
| GHI | 15 |
| JKA | 0 |
| LMN | 0 |
| OPQ | 0 |
+--------+----------+
You would to invert the tables in the left join, so that vehicules with no fueling do appear in the resultset (as it is, your left join allows for fueling without vehicules, which does not look like a relevant use case).
I would also recommend prefixing the column names with the table they come from to avoid ambiguity.
Finally, to return 0 (instead of null) for the vehicules that had no fueling, you can use coalesce().
select("tbl_vehicle.reg_no, coalesce(sum(fuel_qty), 0) fuel_qty")
->from('tbl_vehicle')
->join('tbl_direct_fuel', 'tbl_direct_fuel.vehicle = tbl_vehicle.vehicle_id', 'left')
->group_by ('tbl_vehicle.vehicle_id')
Try:
select t1.reg_no, t2.fuel_total
from tbl_vehicle t1
left join (
select vehicle_id, sum(fuel_qty) fuel_total
from tbl_direct_fuel
group by vehicle_id
) t2 on t1.vehicle_id = t2.vehicle_id

How to query closest date and display the specific data

Hi guys i have a problem displaying a data from my query code.
I want to display a data from the closest date today. Below is my sample data and my output data that i want to display.
Landing Area data
|landing_id| id_number| address |
---------------------------------
| 1 | 00012345 | Ozamiz |
| 2 | 00012346 | Tudela |
| 3 | 00012347 | Nailon |
| 4 | 00012348 | Taboo |
| 5 | 00012349 | Jimenez |
| 6 | 00012350 | Tangub |
---------------------------------
Percentage data
|percent_id| landing_id | percentage | date_added |
-----------------------------------------------------------
| 1 | 1 | 9 |2018-10-08 21:42:22 |
| 2 | 1 | 12 |2018-10-03 20:43:32 |
| 3 | 1 | 43 |2018-10-15 19:43:49 |
| 4 | 3 | 22 |2018-10-10 15:43:56 |
| 5 | 3 | 77 |2018-10-12 18:44:03 |
-----------------------------------------------------------
And this is my query code.
SELECT fish_landing.landing_id,
percentage.landing_id as percentage_landing_id,
percentage.percentage,
percentage.date_added
FROM percentage
RIGHT OUTER JOIN fish_landing ON percentage.landing_id = fish_landing.landing_id
ORDER BY fish_landing.landing_id ASC
The output of my code is this, where the date_added and the percentage is not exact.
|percent_id| percentage | date_added |
----------------------------------------------
| 1 | 9 |2018-10-08 21:42:22 |
| 2 | | |
| 3 | 22 |2018-10-10 15:43:56 |
| 4 | | |
| 5 | | |
| 6 | | |
----------------------------------------------
And the output data that I want to display is the table below, where the percentage that has a latest date_added in every landing_id will be display.
|landing_id| percentage | date_added | address |
--------------------------------------------------------
| 1 | 43 |2018-10-15 19:43:49 | Ozamiz |
| 2 | | | |
| 3 | 77 |2018-10-12 18:44:03 | Nailon |
| 4 | | | |
| 5 | | | |
| 6 | | | |
--------------------------------------------------------
I hope you can help me in my problem.
You can get maximum date_added for a landing_id in a separate derived table and use it for joining.
Try the following:
SELECT fish_landing.landing_id,
percentage.percentage,
percentage.date_added,
fish_landing.address
FROM fish_landing
LEFT JOIN percentage ON percentage.landing_id = fish_landing.landing_id
LEFT JOIN (SELECT landing_id, MAX(date_added) AS max_date_added
FROM percentage
GROUP BY landing_id) AS dt
ON dt.landing_id = percentage.landing_id AND
dt.max_date_added = percentage.date_added
ORDER BY fish_landing.landing_id ASC

Query equivalent to two group by's without a subquery?

I'm trying to run a report on User ACL's. We use MYSQL and my we're prohibited from using subqueries for performance reasons. The goal is to turn this:
--------------------------------
| userName | folderID | roleID |
--------------------------------
| gronk | 1 | 1 |
| gronk | 2 | 2 |
| gronk | 4 | 2 |
| tbrady | 1 | 2 |
| jedelman | 1 | 1 |
| jedelman | 2 | 1 |
| mbutler | 1 | 2 |
| mbutler | 2 | 2 |
| bill | 1 | 3 |
| bill | 2 | 3 |
| bill | 3 | 3 |
| bill | 4 | 3 |
--------------------------------
Into this:
------------------------
| Lowest Role | Number |
------------------------
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
------------------------
I can see how to do it with a subquery. The inner query would do a group by on userName with a min(roleID). Then the outer query would do a group by on the lowest role and count(*). But I can't see how to do it without a subquery.
Also, if it helps I created a SQL Fiddle that has the data above.
I found a solution using a left join:
select UFM.roleID, count(distinct UFM.userName)
from UserFolderMembership UFM
left join UserFolderMembership UFM2 on
UFM.userName = UFM2.userName and
UFM.roleID > UFM2.roleID
where
UFM2.userName is null
group by
UFM.roleID

MYSQL Union Operation with Gross, Cut & Net Amounts

I need to print Gross allocation, Cut Allocation & Net Allocation issued for various offices under relevant votes. I used the following tables.
1) Total issues (Gross Allocation) are in the Table, Named "issues_tot"
+---------+------+------------+
| v_code | oid | amount |
+---------+------+------------+
| 1 | 2 | 200,000.00 |
| 1 | 3 | 80,000.00 |
| 2 | 1 | 40,000.00 |
| 3 | 2 | 150,000.00 |
+---------+------+------------+
2) Cut amounts (Cut Allocation) are in the Table, Named "cp_tot"
+--------+-----+-----------+
| v_code | oid | amount |
+--------+-----+-----------+
| 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 3 | 2 | 75,000.00 |
+--------+-----+-----------+
3) Table, Named "vote"
+--------+-------------------------+
| v_code | vote |
+--------+-------------------------+
| 1 | 001-2-6-3-2502 |
| 2 | 001-1-4-21-2202 |
| 3 | 101-1-2-0-1405 |
+--------+-------------------------+
4) Table, Named "office"
+-----+----------------------+
| oid | office |
+-----+----------------------+
| 1 | Weeraketiya |
| 2 | Tissamaharama |
| 3 | District Sec |
+-----+----------------------+
And desired output as follows:
+--------+------------+-----------+------------+
| v_code | Gross | Cut | Net |
+--------+------------+-----------+------------+
| 1 | 200,000.00 | 68,000.00 | 132,000.00 |
| 1 | 80,000.00 | 50,000.00 | 30,000.00 |
| 2 | 40,000.00 | 0.00 | 40,000.00 |
| 3 | 150,000.00 | 75,000.00 | 75,000.00 |
+--------+------------+-----------+------------+
02) I used the following script to generate that output
select `vote`.`vote` AS `vote`,`office`.`office` AS `office`,
`issues_tot`.`amount` AS `Gross`,
coalesce(`cp_tot`.`amount`,0) AS `Cut`,
(`issues_tot`.`amount` - coalesce(`cp_tot`.`amount`,0)) AS `Net`
from (((`vote` join `issues_tot` on((`vote`.`v_code` = `issues_tot`.`v_code`))) join
`office` on((`office`.`oid` = `issues_tot`.`oid`))) left join
`cp_tot` on((`issues_tot`.`v_code` = `cp_tot`.`v_code`)))
But it generates the following output with repeated records:
+------------+----------------+--------------+-------------+--------------+
| Vote | Office | Gross | Cut | Net |
+---------------+-------------+--------------+-------------+--------------+
| 001-2-6-3-2502| Tissamaharama | 200,000.00 | 68,000.00 |132,000.00 |
| 001-2-6-3-2502| Tissamaharama | 200,000.00 | 50,000.00 | 150,000.00 |
| 001-2-6-3-2502| District Sec | 80,000.00 | 68,000.00 | 12,000.00 |
| 001-2-6-3-2502| District Sec | 80,000.00 | 50,000.00 | 30,000.00 |
| 001-1-4-21-2202| Weeraketiya | 40,000.00 | - | 40,000.00 |
| 101-1-2-0-1405 | Tissamaharama | 150,000.00 | 75,000.00 | 75,000.00 |
+------------+-----------------+--------------+-------------+--------------+
I can not understand what was going wrong. Can anyone help me?
Firstly, the following query will get what you want:
select
v.vote,
o.office,
it.amount as Gross,
coalesce(ct.amount , 0) as Cut,
it.amount - coalesce(ct.amount, 0) as Net
from issues_tot it
left join cp_tot ct
on it.v_code = ct.v_code
and it.oid = ct.oid
left join vote v
on it.v_code = v.v_code
left join office o
on it.oid = o.oid
order by it.v_code
and SQLFiddle Demo Here, the only issue is that you forget to match oid between issues_tot and cp_tot.
If there is no oid criteria, the match will do like following:
# issues_tot # cp_tot
| v_code | oid | amount | | v_code | oid | amount |
+---------+------+------------+ +--------+-----+-----------+
| 1 | 2 | 200,000.00 | -> | 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 1 | 3 | 80,000.00 | -> | 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 2 | 1 | 40,000.00 | -> no record match
| 3 | 2 | 150,000.00 | -> | 3 | 2 | 75,000.00 |
so 6 records by your query is it.

MySQL, ordering GROUP BY

I have a table that has some values in it, along with the time that value was taken against an associated ID from another table.
I am looking to retrieve the latest value for every item in that table, and then order by those latest values.
Here is an SQL fiddle, http://www.sqlfiddle.com/#!2/0be99
And here is text output.
'hist' table
| HIST_ID | HIST_ITEM_ID | HIST_VALUE | HIST_TIME |
|---------|--------------|------------|------------|
| 1 | 1 | 1 | 1420291000 |
| 2 | 1 | 2 | 1420292000 |
| 3 | 1 | 3 | 1420293000 |
| 4 | 1 | 5 | 1420294000 |
| 5 | 1 | 10 | 1420295000 |
| 6 | 1 | 50 | 1420296000 |
| 7 | 1 | 60 | 1420297000 |
| 8 | 1 | 77 | 1420298000 |
| 9 | 1 | 90 | 1420299000 |
| 10 | 1 | 101 | 1420300000 |
| 11 | 2 | 1 | 1420291000 |
| 12 | 2 | 3 | 1420292000 |
| 13 | 2 | 7 | 1420293000 |
| 14 | 2 | 9 | 1420294000 |
| 15 | 2 | 15 | 1420295000 |
| 16 | 2 | 21 | 1420296000 |
| 17 | 2 | 33 | 1420297000 |
| 18 | 2 | 35 | 1420298000 |
| 19 | 2 | 55 | 1420299000 |
| 20 | 2 | 91 | 1420300000 |
'items' table
| ITEM_ID | ITEM_TITLE |
|---------|------------|
| 1 | ABCD |
| 2 | XYZ123 |
So, I can do something like...
select * from hist
inner join items on hist_item_id = item_id
group by hist_item_id
order by hist_value desc
However this returns me a grouping that I cannot order. How can I order this grouping? I had a look at other similar questions on here but was unable to apply their solutions successfully to my query to produce the desire result.
The desired result here would be to return.
HIST_ITEM_ID | ITEM_TITLE | HIST_VALUE |
|------------|------------|------------|
| 1 | ABCD | 101 |
| 2 | XYZ123 | 91 |
You can use a join to get the most recent history item. Then you can join back to the history table and the item table to get additional information:
select h.*, i.item_title
from (select hist_item_id, max(hist_id) as max_hist_id
from hist
group by hist_item_id
) hh join
hist h
on h.hist_id = hh.max_hist_id join
items i
on i.item_id = hh.hist_item_id;
Here is a SQL Fiddle.
You should use MAX function and group by the item id. That would look like this:
SELECT i.item_id, i.item_title, MAX(h.hist_value)
FROM items AS i
INNER JOIN hist AS h
ON i.item_id = h.hist_item_id
GROUP BY i.item_id