I want to select the columns with the max number of canceled trip. I know how to count the number of trips using the SQL statement, however, when I try to use the max function it gives the invalid group function error.
my SQL statement is as below:enter image description here
select t.ServiceNumber, t.RouteNumber, remark,
max(count(if(Cancelled =1 ,1,null))) as"Total Cancelled Trip"
from trip t inner join
route r
on r.ServiceNumber = t.ServiceNumber and
r.RouteNumber = t.RouteNumber
group by t.ServiceNumber, t.RouteNumber,remark;
If you want just one row with the maximum, you can do:
select t.ServiceNumber, t.RouteNumber, remark,
count(*) as "Total Cancelled Trip"
from trip t inner join
route r
on r.ServiceNumber = t.ServiceNumber and
r.RouteNumber = t.RouteNumber
where Cancelled = 1
group by t.ServiceNumber, t.RouteNumber, remark
order by count(*) desc
limit 1;
Getting all such rows in the event of ties is tricky in MySQL. Perhaps the easiest way uses variables:
select tr.*
from (select t.ServiceNumber, t.RouteNumber, remark,
count(*) as "Total Cancelled Trip",
(#maxtct = greatest(#maxtct, count(*))
from trip t inner join
route r
on r.ServiceNumber = t.ServiceNumber and
r.RouteNumber = t.RouteNumber cross join
(select #maxtct := 0) params
where Cancelled = 1
group by t.ServiceNumber, t.RouteNumber, remark
) tr
where `Total Cancelled Trip` = #maxtct;
Related
I am trying to calculate the checkout conversion by using the following query but I keep getting error:
SELECT
(SELECT seller.name, count(checkout.id) AS 'Completed_checkout'
FROM checkout
JOIN seller
ON seller.id = checkout.seller_id
WHERE checkout.completed = 1
GROUP BY seller.name)
/
(SELECT seller.name, count(checkout.id) AS 'Total_Checkouts'
FROM checkout
JOIN seller
ON seller.id = checkout.seller_id
GROUP BY seller.name) * 100
AS 'Checkout_Converstion';
The end goal after being able to calculate it is:
filter by seller with more than 15 checkouts total
order it by DESC
limit it by then 5 first records
Any ideas on how to make this work?
How about simplifying this?
SELECT s.name, AVG(co.completed) as completed_ratio
FROM checkout co JOIN
seller s
ON s.id = co.seller_id
GROUP BY s.name;
If you want the counts:
SELECT s.name, AVG(co.completed = 1) as completed_ratio,
SUM(c.completed = 1) as num_completed,
COUNT(*) as total
FROM checkout co JOIN
seller s
ON s.id = co.seller_id
GROUP BY s.name;
These make use of the fact that MySQL treats boolean expressions as numbers in a numeric context -- with "1" for true and "0" for false.
You can do it with 1 query:
SELECT s.name,
100 * AVG(c.completed) AS Checkout_Conversion
FROM checkout c JOIN seller s
ON s.id = c.seller_id
GROUP BY s.id, s.name
HAVING SUM(c.completed) > 15
ORDER BY Checkout_Conversion DESC
LIMIT 5
I have the following schema:
http://sqlfiddle.com/#!9/bd3a4/1
I would like to
group by date() and add where user_id = ?..
per day and count the results per day.
required result Day|TotalRequests|TotalOrders
Since you could have an order on Day 1, and a request on Day 8, you may have entries on one side but not the other. To qualifify your needs, I would do a UNION of all orders and requests individually by date. Then roll those values up. The inner Pre-Aggregate result query is where the WHERE clause per user would be applied. The pre-aggregate query also has a recSource column to indicate where the record originated from as 'O' from orders and 'R' from requests, so the roll-up knows which column to store the total count respectively.
select
preAgg.recDate,
SUM( case when preAgg.recSource = 'O' then preAgg.recCount else 0 end ) as OrderCount,
SUM( case when preAgg.recSource = 'R' then preAgg.recCount else 0 end ) as RequestCount
from
( select
date(o.created_at) recDate,
'O' as recSource,
count(*) as recCount
from
orders o
where
o.user_id = 3
group by
date(o.created_at)
UNION ALL
select
date(r.created_at) recDate,
'R' as recSource,
count(*) as recCount
from
requests r
where
r.user_id = 3
group by
date(r.created_at) ) preAgg
group by
preAgg.recDate
order by
preAgg.recDate
For query optimization, I would ensure your order and request table both have have an index on ( user_id, created_at ).
SQL Fiddle result
You can use the following query:
SELECT
DATE(o.created_at) AS Day
,COUNT(r.id) AS TotalRequests
,COUNT(o.id) AS TotalOrders
FROM orders o
LEFT JOIN
requests r ON
r.id = o.request_id
WHERE o.user_id = 3
GROUP BY DATE(r.created_at), DATE(o.created_at),o.user_id
I have this query that I use in order to get records from several tables, using JOIN.
SELECT c.id AS contestant_id,
c.created_date,
c.name AS contestant_name,
counter.total AS score,
c.email
FROM submission AS s,
(SELECT ans.id AS ans_id, sub.contestant_id, count(sub.id) AS total
FROM submission AS sub
JOIN (SELECT id, is_true FROM answer) AS ans
WHERE sub.answer_id = ans.id
AND ans.is_true = 1
GROUP BY sub.contestant_id) AS counter
JOIN (SELECT id, name, email, type, created_date
FROM contestant
WHERE contest_type = 1
AND submission_status = 1) AS c
WHERE counter.contestant_id = c.id
GROUP BY c.id
ORDER BY c.created_date DESC
The problem is that each record in table contestant will have 30 record in the submission table. So, when I retrieve 1000 contestant or more, the server hangs.
Please try the following restructured query:
SELECT
c.id AS contestant_id,
c.created_date,
c.name AS contestant_name,
counter.total AS score,
c.email
FROM
(
SELECT
sub.contestant_id, count(sub.id) AS total
FROM
submission AS sub
JOIN answer AS ans
ON sub.answer_id = ans.id AND ans.is_true = 1
GROUP BY
sub.contestant_id
)
AS counter
JOIN contestant c
ON c.contest_type = 1 AND c.submission_status = 1 AND c.id = counter.contestant_id
WHERE
counter.contestant_id = c.id
GROUP BY
c.id
ORDER BY
c.created_date DESC
It is possible to change the query result row limit, or remove the limit entirely.
Go to "Edit -> Preferences... -> SQL Editor (tab)"
Locate the "Query Results" section and untick the "Limit Rows" checkbox
Click "OK"
Re-run your query
Exporting query results in MySQL Workbench beyond 1000 records
I'm trying to fetch the lowest price per day per hotel, I get multiple results.
I first try to fetch the lowest amount with the MIN() function, then inner join.
When i later try to group by outside the subquery, it just groups by the lowest id.
The SQL itself:
SELECT mt.id, mt.amount, mt.fk_hotel, mt.start_date
FROM price mt
INNER JOIN
(
SELECT price.id, MIN(price.amount) minAmount
FROM price
WHERE 1=1 AND price.start_date >= '2014-10-08' AND price.start_date <= '2014-10-10' AND price.active = 1 AND price.max_people = 2
GROUP BY id
) t
ON mt.id = t.id AND mt.amount = t.minAmount
ORDER BY mt.fk_hotel, mt.amount;
And the results looks like this:
http://jsfiddle.net/63mg3b2j/
I want to group by the start date and fk_hotel so that it groups by the lowest amount value, can anybody help me? Am I being clear?
Edit: I also need a field fk_room from the corresponding row, so i can inner join
Try this:
SELECT MIN(mt.amount) AS min_amount, mt.fk_hotel, mt.start_date
FROM price mt
WHERE
mt.active = 1 AND
mt.max_people = 2 AND
mt.start_date >= '2014-10-08' AND mt.start_date <= '2014-10-10'
GROUP BY mt.fk_hotel, mt.start_date
ORDER BY mt.fk_hotel, min_amount;
Well first of all get a table with minimum value in top row using ORDER BY and then GROUP BY for your required result
SELECT mt.id, mt.amount, mt.fk_hotel, mt.start_date
FROM
(SELECT id, amount, fk_hotel, start_date
FROM price
WHERE start_date >= '2014-10-08' AND start_date <= '2014-10-10'
AND active = 1 AND max_people = 2
ORDER BY amount DESC) AS mt
GROUP BY mt.id
Well I had to still go with a subquery, cause i needed some additional foreign key fields from the corresponding row to inner join some other stuff. It isn't a great solution, cause it fetches too much stuff, the rest is filtered out programmatically.
The most annoying thing here, when I try to use MIN() or MAX() function and get the appropriate fields to that row, it fetches the first results from the DB, which are incorrect and so i have to use a subquery to inner join to get the other fields, I can use grouping, but I had too many fields to group. Maybe I'm missing something. The amount of data doesn't grow in time, so I guess it works for me. So this is the final SQL i came up with, for future reference..
SELECT mt.*, roomtype.name roomname, hotel.name hotelname
FROM booking.price mt
INNER JOIN roomtype ON roomtype.id = mt.fk_roomtype
INNER JOIN hotel ON hotel.id = mt.fk_hotel
INNER JOIN(
SELECT price.id, MIN(price.amount) minAmount
FROM booking.price WHERE 1=1 AND price.start_date >= '2014-10-22' AND price.start_date <= '2014-10-31' AND price.max_people = 2 AND price.active = 1
GROUP BY id
) t
ON mt.id = t.id AND mt.amount = t.minAmount
ORDER BY mt.start_date, mt.amount
I have two tables in my MySQL database: allele and locus. I want to know for a given locus how many alleles there are and of those how many have the status Tentative. I currently have the following query with subquery:
SELECT COUNT(*) as alleleCount,
(SELECT COUNT(*)
FROM allele
INNER JOIN locus ON allele.LocusID = locus.PrimKey
WHERE Status = 'Tentative'
AND locus.ID = 762
) as newAlleleCount
FROM allele
INNER JOIN locus ON allele.LocusID = locus.PrimKey
WHERE locus.ID = 762
but I feel there must be a better way to write this query.
You can use SUM() using sum with condition will result in a boolean 1 or 0 so it will give you the count for your conditions
SELECT locus.ID,COUNT(*) `all_alleles_per_locus`,
SUM(Status = 'Tentative') `tentative_alleles_762`
FROM allele
INNER JOIN locus ON allele.LocusID = locus.PrimKey
GROUP BY locus.ID
One way would be to group the locus by its statuses and fetch each status's respective count; using the WITH ROLLUP modifier will add a NULL status at the end representing the total:
SELECT status, COUNT(*)
FROM allele JOIN locus ON locus.PrimKey = allele.LocusID
WHERE locus.ID = 762
GROUP BY status WITH ROLLUP
If you absolutely do not want a list of all statuses, you can instead GROUP BY status = 'Tentative' (optionally WITH ROLLUP if desired)—but it will not be sargable.