where and having precedence in mysql query - php

I have been having problems with this query for close to 3 hours and no amount of googling is helping me so far:
select id,nombres,apaterno,amaterno, (select sum(cargo) from tb_consultorios_recibos_transacciones where id_paciente = tb_consultorios_pacientes.id and date(fecha_trans)>='2015-03-01' and date(fecha_trans)<='2015-03-31') as cargospaciente, (select sum(abono) from tb_consultorios_recibos_transacciones where id_paciente = tb_consultorios_pacientes.id and date(fecha_trans)>='2015-03-01' and date(fecha_trans)<='2015-03-31') as abonospaciente from tb_consultorios_pacientes where id_consultorio = 3 order by apaterno asc, cargospaciente desc
besides the where clause, I would like only to display rows where the alias cargospaciente or abonospaciente are greater than 0, this is the query I am trying which is obviously not working:
select id,nombres,apaterno,amaterno, (select sum(cargo) from tb_consultorios_recibos_transacciones where id_paciente = tb_consultorios_pacientes.id and date(fecha_trans)>='2015-03-01' and date(fecha_trans)<='2015-03-31') as cargospaciente, (select sum(abono) from tb_consultorios_recibos_transacciones where id_paciente = tb_consultorios_pacientes.id and date(fecha_trans)>='2015-03-01' and date(fecha_trans)<='2015-03-31') as abonospaciente from tb_consultorios_pacientes where id_consultorio = 3 having (cargospaciente>0 or abonospaciente>0) order by apaterno asc, cargospaciente desc
any help on how to specify having and where in the same clause?

Try it like below rather; by getting the sum of required column with proper grouping and then join that result set with outer select result
select tcp.id,
tcp.nombres,
tcp.apaterno,
tcp.amaterno,
tab.sum_cargo,
tab.sum_abono
from tb_consultorios_pacientes tcp
join
(
select id_paciente, sum(cargo) as sum_cargo, sum(abono) as sum_abono
from tb_consultorios_recibos_transacciones
where date(fecha_trans)>='2015-03-01'
and date(fecha_trans)<='2015-03-31'
group by id_paciente
having sum_cargo > 0 or sum_abono > 0
) tab
on tcp.id = tab.id_paciente
where tcp.id_consultorio = 3
order by tcp.apaterno asc, tcp.cargospaciente desc

Related

How to find first and last values within query sorted by another column

I am new to coding and this is the most complex query I have tried writing.
I am trying to create a query that will find the first and last entry for meters sorted by bunker_id within a date range. There are 12 different systems that have their meters captured when they are used.
I have several MySQL tables to track usage of systems and component configurations.
One table has a log of meters for all the systems. What I am trying to do is query this table between Date A and Date B, and receive the first and last meter values within the date range for each system. They systems may not be used everyday, but on occasion will have multiple entries in a day.
I am looking to have a query run through POST on a web page with selectors for the days and the system id's. The data will be output into an HTML table.
date
bunker_id
power_on_hours
01-01-2022
A
26115.50
01-02-2022
B
28535.13
01-02-2022
A
26257.38
01-03-2022
B
28682.73
What I am trying to return
bunker_id
starting_meters
ending_meters
A
26115.50
26257.38
B
28535.13
28682.73
The query that I have sets the starting and ending hours as the same value. I tried using MAX and MIN, but everything breaks if someone were to enter 0 for the meter.
SELECT
lu_bunkers.bunker_name as 'bunker_name',
lu_bunkers.bunker_sn,
SUM(system_utilization.hours_used) as 'total_hours',
SUM(CASE WHEN system_utilization.use_id = '1' THEN system_utilization.hours_used ELSE 0 END) as 'maintenance_hours',
SUM(CASE WHEN system_utilization.use_id = '2' THEN system_utilization.hours_used ELSE 0 END) as 'working_rf_hours',
SUM(CASE WHEN system_utilization.use_id = '3' THEN system_utilization.hours_used ELSE 0 END) as 'working_no_rf_hours',
SUM(CASE WHEN system_utilization.use_id = '4' THEN system_utilization.hours_used ELSE 0 END) as 'acd_hours',
((SUM(system_utilization.hours_used))/ ((DATEDIFF('2022-02-24', '2021-01-01')+1)*5/7*12))*100 as net_utilization,
((DATEDIFF('2022-02-24', '2021-01-01')+1)*(5/7)*12) as num_hours,
(SELECT system_meters.power_on_hours WHERE system_utilization.date_used BETWEEN '2021-01-01' AND '2022-02-24' ORDER BY system_utilization.date_used DESC LIMIT 1) as 'ending_hours',
(SELECT system_meters.power_on_hours WHERE system_utilization.date_used BETWEEN '2021-01-01' AND '2022-02-24' ORDER BY system_utilization.date_used ASC LIMIT 1) as 'starting_hours'
FROM system_utilization
LEFT JOIN lu_bunkers ON system_utilization.bunker_id = lu_bunkers.bunker_id
LEFT JOIN lu_use ON system_utilization.use_id = lu_use.use_id
LEFT JOIN system_meters ON system_utilization.id = system_meters.utilization_id
WHERE system_utilization.date_used BETWEEN '2021-01-01' AND '2022-02-24' AND system_utilization.bunker_id LIKE '%'
GROUP BY system_utilization.bunker_id
ORDER BY lu_bunkers.bunker_name
2 possible solutions
Using Joins
SELECT
a.`bunker_id`,
b.`power_on_hours` as `starting_meters`,
c.`power_on_hours` as `ending_meters`
FROM `yourtable` a
LEFT JOIN `yourtable` b
ON (
SELECT `date`
FROM `yourtable`
WHERE `bunker_id` = a.`bunker_id`
ORDER BY `date`
LIMIT 1
) = b.`date`
AND a.`bunker_id` = b.`bunker_id`
LEFT JOIN `yourtable` c
ON (
SELECT `date`
FROM `yourtable`
WHERE `bunker_id` = a.`bunker_id`
ORDER BY `date` DESC
LIMIT 1
) = c.`date`
AND a.`bunker_id` = c.`bunker_id`
GROUP BY a.`bunker_id`
Using subqueries on columns
SELECT
a.`bunker_id`,
(
SELECT `power_on_hours`
FROM `yourtable`
WHERE `bunker_id` = a.`bunker_id`
ORDER BY `date` LIMIT 1
) as `starting_meters`,
(
SELECT `power_on_hours`
FROM `yourtable`
WHERE `bunker_id` = a.`bunker_id`
ORDER BY `date` DESC LIMIT 1
) as `ending_meters`
FROM `yourtable` a
GROUP BY a.`bunker_id`

Need to show SQL partial empty results

I need to show empty rows for BRANDS too. I mean, there is a third brand not shown in this query, look:
SELECT
da_brands.name AS brand_name,
COUNT(DISTINCT da_deals.id) AS total_deals,
0 AS total_downloaded_coupons,
0 AS total_validated_coupons,
COUNT(da_logs.id) AS total_likes
FROM
da_brands,
da_deals
LEFT JOIN da_logs
ON da_logs.fk_deal_id = da_deals.id
AND da_logs.fk_deal_id = da_deals.id
AND da_logs.type = 'deal_like'
WHERE da_brands.fk_club_id = 6
AND da_deals.fk_brand_id = da_brands.id
AND da_brands.date <= NOW()
GROUP BY da_brands.name
ORDER BY da_brands.name ASC
RESULTS:
brand_name total_deals total_downloaded_coupons total_validated_coupons total_likes
Marca2 2 0 0 1
Marca1 9 0 0 4
This conditional is showing only brands within deals but i want all brands...:
AND da_deals.fk_brand_id = da_brands.id
Any idea what statement should i use?
Thank you so much.!!!
This following line in the WHERE predicate is the problem...
AND da_deals.fk_brand_id = da_brands.id
You need to LEFT JOIN to da_deals, the same way you did to da_logs, and move that line above into the ON statement for the join.
See below...
SELECT
da_brands.name AS brand_name,
COUNT(DISTINCT da_deals.id) AS total_deals,
0 AS total_downloaded_coupons,
0 AS total_validated_coupons,
COUNT(da_logs.id) AS total_likes
FROM da_brands
LEFT JOIN da_deals
ON da_brands.id = da_deals.fk_brand_id
LEFT JOIN da_logs
ON da_logs.fk_deal_id = da_deals.id
AND da_logs.fk_deal_id = da_deals.id
AND da_logs.type = 'deal_like'
WHERE da_brands.fk_club_id = 6
AND da_brands.date <= NOW()
GROUP BY da_brands.name
ORDER BY da_brands.name ASC

Php count number of how many changed = y where humen=yes

I tried something like this:
$changed = mysql_query("SELECT * FROM games WHERE changed = 'y' AND human = '$_GET[human]' ORDER BY id DESC LIMIT 100", $link);
$num_rowsc = mysql_num_rows($changed);
So what i want is to select last 100 where human = yes and count where changed = y ..
so get last 100 humans and count how many of them have on changed yes
Are you looking for something like this :
$stmt = $pdo->prepare("SELECT COUNT(*) AS cnt FROM ( SELECT * FROM games
WHERE human= :human ORDER BY id DESC LIMIT 100
) WHERE changed = 'y' ");
$stmt->bindParam(':human', $_GET[human]);
$stmt->execute();
Maybe with this query?
SELECT COUNT(*) AS cnt FROM (
SELECT * FROM games
WHERE human = '".mysql_real_escape_string($_GET[human])."'
ORDER BY id DESC LIMIT 100
) tmp WHERE changed = 'y'
1) try using this as your query:
SELECT count(*) FROM (SELECT * FROM games WHERE changed = 'y' ORDER BY id DESC LIMIT 100) WHERE human = '$_GET[human]'
2) use mysqli
select count(*) as cnt from (
SELECT human FROM games WHERE human = '$_GET[human]' ORDER BY id DESC LIMIT 100
) as changes WHERE changed = 'y'

Order by result of a query / Mysql Subquery

Hi there (I'm new to PHP),
I can't quite figure out the syntax of a subquery I'm trying to make, this is the query:
SELECT * FROM show_episode, shows, show_episode_airdate, show_moyenne
WHERE season = 1 AND episode = 1
AND shows.imdb_id = show_episode.imdb_id_show
AND show_episode_airdate.episode_id = show_episode.episode_id
AND show_moyenne.show_id = shows.id
AND show_episode_airdate.airdate < '2013-07-12'
ORDER BY show_episode_airdate.airdate DESC LIMIT 10
Once this was done, I wanted to order those 10 selected rows by show_moyenne.moyenne with something like that:
SELECT * (FROM show_episode, shows, show_episode_airdate, show_moyenne
WHERE season = 1 AND episode = 1
AND shows.imdb_id = show_episode.imdb_id_show
AND show_episode_airdate.episode_id = show_episode.episode_id
AND show_moyenne.show_id = shows.id
AND show_episode_airdate.airdate < '2013-07-12'
ORDER BY show_episode_airdate.airdate DESC LIMIT 10)
* ORDER BY show_moyenne.moyenne DESC
Which is not correct, anybody can show me the right way to do this ?
Thanks, any help appreciated!
Select * from
(SELECT * FROM show_episode, shows, show_episode_airdate, show_moyenne
WHERE season = 1 AND episode = 1
AND shows.imdb_id = show_episode.imdb_id_show
AND show_episode_airdate.episode_id = show_episode.episode_id
AND show_moyenne.show_id = shows.id
AND show_episode_airdate.airdate < '2013-07-12'
ORDER BY show_episode_airdate.airdate DESC LIMIT 10) as j
order by j.moyenne DESC
I hope this can be of some help.
SELECT x.*
FROM
( SELECT *
FROM show_episode e
JOIN shows s
ON s.imdb_id = e.imdb_id_show
JOIN show_episode_airdate a
ON a.episode_id = e.episode_id
JOIN show_moyenne m
ON m.show_id = s.id
WHERE season = 1
AND episode = 1
AND a.airdate < '2013-07-12'
ORDER
BY a.airdate DESC
LIMIT 10
) x
ORDER
BY moyenne;

SQL: Forum Order by behaviour (in Codeigniter)

Here's the situation:
In my database i have a table with threads, and a table with replies. Both have a Timestamp field.
Now i am developing a forum and wish to order threads in the following manner:
If the thread has replies, then: ORDER BY tblReply.Timestamp DESC
Else, the thread has no replies: ORDER BY tblThread.Timestamp DESC
I do not know how to combine these 2 in one statement.
My query as it is now:
SELECT `PK_ThreadID`, `Title`, `tblUsers`.`Username`, `tblThread`.`Date`, count(tblReply.FK_ThreadID) AS number_replies FROM (`tblThread`)
JOIN `tblUsers` ON `tblUsers`.`PK_UserID` = `tblThread`.`FK_UserID`
LEFT JOIN `tblReply` ON `tblReply`.`FK_ThreadID` = `tblThread`.`PK_ThreadID`
WHERE `isExpertQuestion` = 0 AND `isPublic` = 1
GROUP BY `PK_ThreadID`
ORDER BY max(tblReply.Date)` desc
//Here it only orders by reply date, so threads with no replies appear at the bottom
How do i achieve the ordering i want in this query?
Like this probably:
SELECT `PK_ThreadID`, `Title`,
`tblUsers`.`Username`,
`tblThread`.`Date`,
count(tblReply.FK_ThreadID) AS number_replies
FROM (`tblThread`)
JOIN `tblUsers` ON `tblUsers`.`PK_UserID` = `tblThread`.`FK_UserID`
LEFT JOIN `tblReply` ON `tblReply`.`FK_ThreadID` = `tblThread`.`PK_ThreadID`
WHERE `isExpertQuestion` = 0 AND `isPublic` = 1
GROUP BY `PK_ThreadID`
ORDER BY
CASE WHEN COUNT(tblReply.FK_ThreadID) > 0 THEN tblReply.Timestamp
WHEN COUNT(tblReply.FK_ThreadID) = 0 OR tblReply.FK_ThreadID IS NULL
THEN tblThread.Timestamp
END DESC

Categories