sqlalchemy SELECT column FROM (SELECT columns FROM TABLE) - sqlalchemy

I have the following query
reports = self.session.query((
func.sum(Report.a) / func.sum(Report.b))
.label('c'),
Report.id,
Report.id2
).group_by(Report.id, Report.id2
)
I now want to get the max(c) for the reports, grouped by id.
Essentially, I am trying to have a sqlalchemy solution to this problem
SQL Select only rows with Max Value on a Column
but with the extra requirement that I need to calculate the value column I want to have the max in as in Selecting max value from calculated column in mysql
I am finding it difficult to perform a
SELECT MAX(C), id FROM (SELECT A/B AS C, id FROM TABLE) t

Mark your first query as subquery:
reports = session.query(
(func.sum(Report.a) / func.sum(Report.b)).label('c'),
Report.id,
Report.id2
).group_by(Report.id, Report.id2).subquery()
After this it can be used in another query as if it was a table:
# reports.c is a shorthand for reports.columns
q = session.query(
func.max(reports.c.c),
reports.c.id
).group_by(reports.c.id)

Related

MYSQL GROUP BY on 2 Tables with MAX

I have 2 mysql tables:
record table:
and
race table:
I want to select the records from the 1st table group by id_Race but only the MAX from column "secs".
I tried the following but didnt work:
$query = "SELECT rec.RecordsID,rec.id_Athlete,rec.date_record,rec.id_Race,rec.placeevent,rec.mins,rec.secs,rec.huns,rec.distance,rec.records_text,r.name,MAX(rec.secs)
FROM records AS rec INNER JOIN race AS r ON r.RaceID=rec.id_Race WHERE (id_Athlete=$u_athlete) GROUP BY rec.id_Race;";
($u_athlete is a variable i get from _SESSION)
Can you help me about that?
Thank you.
When you use an aggregation function like MAX and select all fields, you are forced to include all selected fields that are not affected by the MAX inside the GROUP BY clause.
Though you can use a window function like ROW_NUMBER that will group by specifically on id_Race and order by the secs column in a descendent way (so that the highest value of secs will be associated with row_number=1).
Afterwards you can select the rows which have row_number=1 and the id_Athlete you pass using the variable.
SELECT
rec.RecordsID,
rec.id_Athlete,
rec.date_record,
rec.id_Race,
rec.placeevent,
rec.mins,
rec.secs,
rec.huns,
rec.distance,
rec.records_text,
race.name,
FROM
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY id_race ORDER BY secs) rank
FROM
record
) rec
INNER JOIN
race race
ON
race.RaceID=rec.id_Race
WHERE
rec.rank = 1
AND
rec.id_Athlete = $u_athlete;

How to aggregate SQL query and display result in a different column?

I've a MY-SQL query which is pulling a set of records from database. I want to aggregate slightly different way to use in my application. When duplicate rows present in record set with same ticker value query will sum up est_units and est_trans_value and display in new columns as total_est_units and total_est_trans_value. If there is no duplicate with same ticker value it should display total_est_units as est_units and total_est_trans_value as est_trans_value. How can I do this -- Can you please help to modify this query?
SQL:
SELECT
oc.*
FROM
order_confirm_daily oc
INNER JOIN
(SELECT
id, ticker, MAX(est_order_time) AS mts
FROM
order_confirm_daily
WHERE DATE(est_order_time) LIKE '2021-04-26%'
GROUP BY ticker) ds ON ds.ticker = oc.ticker
AND oc.est_order_time = ds.mts;
Sample Data:
desired results: Added two new derived column "total_est_units" and "Total_est_trans_value" which will display Sum of est_units and est_trans_value respectively only when multiple rows present with same ticker -- here it is "TNA" highlighted in screen shot.
I see. You just want window functions:
select oc.*,
sum(est_units) over (partition by ticker) as total_est_units,
sum(est_trans_value) over (partition by ticker) as total_est_trans_value
from order_confirm_daily oc;
EDIT:
In older versions of MySQL, you would use JOIN and GROUP BY:
select *
from order_confirm_daily oc join
(select ticker, sum(est_units) as total_est_units,
sum(est_trans_value) as total_est_trans_value
from order_confirm_daily oc
group by ticker
) oct
using (ticker);

How to assign a new column name to the sum of columns aggregated in a mysql query

I need to assign a name to the sum of columns aggregated in a mysql query.
This is what is tried:
SELECT
JSON_LENGTH(comments) as c_total,
JSON_LENGTH(likes) as l_total,
(c_total+l_total) as total
FROM posts
Comments and likes columns holds data in json data type.
JSON_LENGTH returns the length of the array.
How can ı get the total value in above example ?
You can reference select fields if they're in subqueries:
SELECT c_total + l_total AS Total
FROM (
SELECT
JSON_LENGTH(comments) as c_total,
JSON_LENGTH(likes) as l_total,
(c_total+l_total) as total
FROM posts
) A
;
otherwise I think you have to repeat the logic:
SELECT
JSON_LENGTH(comments) as c_total,
JSON_LENGTH(likes) as l_total,
(JSON_LENGTH(comments) + JSON_LENGTH(likes)) as total
FROM posts
;

How to Select 3 random rows per group in same table - MYSQL

I have a table that has multiple categories (c) & I'd like to select 3 random rows for each category each time I run this query. I got it to select 3 just fine but noticed it wasn't selecting random rows, but instead the same rows each time. So I'm back to square one with my query.
select PLAYERID,
NAME,
RACEID,
VALUE,
MA,
ST,
AG,
LEVEL,
SKILLS,
XP,
TYPE
FROM FAPLAYER
GROUP BY TYPE
ORDER BY RAND()
I'm trying to get 3 of each TYPE from the FAPLAYER table where I have probably around 50 different TYPE's.
Here's my query output for a basic query with RAND
Solution 1: Looks like "GROUP BY TYPE" is giving you trouble. Try this:
SELECT * FROM FAPLAYER
ORDER BY RAND()
LIMIT 3;
Solution 2:
Do you have a column with ID which auto increment? If so then you can do the following max=50, min=1:
SET #rand_id = (SELECT FLOOR((RAND() * (max-min+1))+min));
SELECT *
FROM FAPLAYER
WHERE RACEID = #rand_id

How to Display 1 Column sum in other Column

I have a table that has different columns display different values.
I need to add a new column that displays sum of 1 column in each row of other column.
This is what i need to display.
I have written following query but its only displaying 1 in each row of last column.
select inStation.name TapInStation , outStation.name TapOutStation,
count(trx.passengerCount) PassengerCount, sum(trx.amount) Fare,
(select sum(passengerCount) from transactions iTrx
where iTrx.ID = trx.ID) PassengerPercent
from transactions trx
inner join
station inStation on inStation.ID = trx.fromStation
inner join
station outStation on outStation.ID = trx.toStation
GROUP BY
TapInStation, TapOutStation
If you want the total, then remove the correlation clause. This may do what you want:
select inStation.name as TapInStation , outStation.name as TapOutStation,
count(trx.passengerCount) as PassengerCount,
sum(trx.amount) as Fare,
(select sum(passengerCount) from transactions iTrx) as PassengerPercent
I'm not sure why you would called the "total" something like PassengerPercent, but this should return the overall total.
I also suspect that you might want a sum() for the previous expression.