Use max column value in order by - mysql

I'm trying to order a table by two columns, each with a different weighting. The first is uptime, which is a value between 0 and 1 and has a weighting of 0.3. The second is votes, which is a non-negative integer and has a weighting of 0.7.
The weighting needs to be multiplied by a value between 0-1, so I'm going to get this for votes by dividing the number of votes for each row by the maximum number of votes held by any row.
This is my query so far, and it almost works:
SELECT addr
FROM servers
ORDER BY (0.3 * uptime) +
(0.7 * (votes / 100)) DESC
The 100 is hard-coded and should be the maximum value of votes. Using MAX(votes) makes the query return only the record with highest number of votes. Can this be done in a single query?

You could use a subquery for selecting the maximum value of votes
SELECT addr
FROM servers
ORDER BY (0.3 * uptime) +
(0.7 * (votes / (SELECT MAX(votes) FROM servers))) DESC
Example fiddle here.

Define a variable and use it:
DECLARE #maxVotes int
SELECT #maxVotes = MAX(votes) from servers
SELECT addr
FROM servers
ORDER BY (0.3 * uptime) +
(0.7 * (votes / #maxVotes)) DESC
or use a subquery in the order by:
SELECT addr
FROM servers
ORDER BY (0.3 * uptime) +
(0.7 * ( votes / (SELECT MAX(votes) FROM servers))) DESC

Related

MYSQL Calculate Conversion Rate

I could manage to return the correct Conversion Rate with this query:
SELECT
date(ordertime),
(count(*) / (
SELECT
sum(uniquevisits)
FROM
s_statistics_visitors
WHERE
datum = '2020-11-25') * 100) AS 'CONVERSION RATE'
FROM
s_order
WHERE
date(ordertime) = '2020-11-25'
AND subshopID = 1
GROUP BY
date(ordertime);
But it only returns the CR for one specific date. It wont work with the between keyword.
The subquery returns more then one result, if I delete the where condition in the subquery.
Schema for s_statistics: id, shopID, datum, uniquevisits, devicetype
Schema for s_order: id, ordernumber, ordertime, shopID
Since s_statistics saves values for each devicetype I have to sum uniquevisits per day. But the group by date(ordertime) at the end of my query does not affect the subquery.
-original post-
I want to calculate the conversion rate for an onlineshop.
The data is held in two tables.
Schema1 statistics: id / shopID / datum(yyyy-mm-dd) / uniquevisits / devicetype
Schema2 order: id / ordernumber / ordertime (YYYY-MM-DD HH-MM-SS)
Upon my knowledge the conversionrate calculates like:
(unique visits per day / 1000) * orders per day
I tried something like this:
SELECT
((count(ordernumber) / 1000) * (select sum(s_statistics_visitors.uniquevisits)
FROM s_statistics_visitors GROUP BY* datum))
FROM s_order where subshopID= '1'
GROUP BY date_format(ordertime, '%d%m%y')
ORDER BY date_format(ordertime, '%d%m%y')
I know that my query wont work - since there is no join - but I believe it might be the right approach. I could you join on the the date.
The problem:
the dateformat in the table: s_statistics_visitors is YYYY-MM-DD
and in order: YYYY-MM-DD HH-MM-SS
You seem to want something like this:
SELECT sv.datum, sv.shopId, count(*) as num_orders,
(count(*) / 1000) / sv.uniquevisits)
FROM s_order o JOIN
s_statistics_visitors sv
ON sv.datum = DATE(o.ordertime) AND
sv.shopId = o.shopId
GROUP BY sv.datum, sv.shopId, sv.uniqevisits ;
Note: This assumes that shopId is in both tables -- which makes sense for how you have described the problem. If not, you can adjust the shop id logic.

How to use SUM and COUNT in sql query

I want to add the total marks of different three table in my database and find the number of students whose marks is less than 80. So I did it this way:
SELECT
(SELECT SUM((totalmarks / 30) * 5) AS marks1 FROM marks) +
(SELECT SUM((totalmarks / 25) * 5) AS marks2 FROM marks2) +
(SELECT SUM((totalmarks / 15) * 5) AS marks3 FROM marks3) AS result
HAVING COUNT((result / 300) * 50) < 80
I am able to get the sum of the marks, but when I put HAVING COUNT condition, it shows nothing. Can someone tell me how to get the number of student using COUNT?
It shows error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'HAVING COUNT((result/300)*50)>80' at line 11 .
Appreciate if someone can help me with this.
enter image description here
You need to group your results by student:
select studID, sum(result) * 5 as result
from (
select studID, totalmarks / 30 as result from marks1
union all
select studID, totalmarks / 25 as result from marks2
union all
select studID, totalmarks / 15 as result from marks3
) as base
group by studID
having ((result / 300) * 50) < 80
NB: it is a bit strange how you divide and multiply. For example, why not the equivalent:
having result < 480
If the logic is that in marks1 the highest possible score is 30, for marks2 25 and for marks3 15, and you want to give each of the three an equal weighting, then indeed you must divide each of the totalmarks as you do.
After the multiplication with five, this would mean the result can never be more than five.
So the having test is then quite superfluous: all results will be below 480.
So maybe you wanted to see who did not have the perfect score, for which the having clause should then be:
having result < 5
Using your current query, it needs a reference table/container to assess the HAVING condition.. so, here's my suggested solution:
SELECT result
FROM (
SELECT (
SELECT SUM(( totalmarks/30 )*5) AS marks1
FROM marks
) + (
SELECT SUM(( totalmarks/25 )*5) AS marks2
FROM marks2
) + (
SELECT SUM(( totalmarks/15 )*5) AS marks3
FROM marks3
) AS `result`
) AS `derived`
HAVING COUNT((result / 300) * 50) < 80

Simple Percentage Column in SQL

I am relatively new to SQL and looking to pick up a few simple tricks. I have managed to create a query that selects each different type of car permit (chargeType), counts the number issued for each one (num), and adds a column that shows the total number of permits issued (total). The code is below.
SELECT chargeType,
COUNT(chargeType) AS num,
(SELECT COUNT(chargeType)
FROM permit) AS total
FROM permit
GROUP BY chargeType
I now want to add a final column which shows the percentage of each permit type issued. So the number of each permit type divided by the total multiplied by 100, but I am struggling to do it. Can anybody help?
Try something like this
SELECT chargeType,
num,
total,
num / NULLIF(total, 0) * 100 AS Percenatge
FROM (SELECT chargeType,
Count(chargeType) AS num,
(SELECT Count(chargeType)
FROM permit) AS total
FROM permit
GROUP BY chargeType) a
NULLIF is used to avoid divide by zero expection
This will work. The plus of this solution is there is no subquery in SELECT
SELECT *, (num * 100 / total) as percentage
FROM
(
SELECT
chargeType,
COUNT(chargeType) AS num,
total,
(num * 100 / total) as percentage
FROM
(SELECT COUNT(chargeType) as total FROM permit) ttotal
CROSS JOIN
permit
GROUP BY
chargeType
) tsub

LIMIT by random number between 1 and 10

Essentially, I want to return X number of records from the last 21 days, with an upper limit of 10 records.
How do I add a random LIMIT to a query in MySQL?
Here's my query, with X for the random number 1-10.
SELECT releases.id, COUNT(charts_extended.release_id) as cnt FROM releases
INNER JOIN charts_extended
ON charts_extended.release_id=releases.id
WHERE DATEDIFF(NOW(), releases.date) < 21
GROUP BY releases.id
ORDER BY RAND()
LIMIT 0, X
I tried using RAND() * 10 + 1, but it gives a syntax error.
Is there any way to do this using pure SQL; ie without using an application language to "build" the query as a string and have the application language fill in X programmatically?
Eureka...
In pseudo code:
execute a query to select 10 random rows
select from that assigning a row number 0-9 using a user defined variable to calculate that
cross join with a single hit on rand() to create a number 0-9 and select all rows with row number less than or equal to that number
Here's the essence of the solution (you can adapt your query to work with it:
select * from (
select *, (#row := coalesce(#row + 1, 0)) row from (
// your query here, except simply LIMIT 10
select * from mytable
order by rand()
limit 10
) x
) y
cross join (select rand() * 10 rand) z
where row <= rand
See SQLFiddle. Run it a few times and you'll see you get 1-10 random rows.
If you don't want to see the row number, you can change the outer select * to select only the specific columns from the inner query that you want in your result.
Your query is correct but you need to update limit clause.
$query = "SELECT releases.id, COUNT(charts_extended.release_id) as cnt FROM releases
INNER JOIN charts_extended
ON charts_extended.release_id=releases.id
WHERE DATEDIFF(NOW(), releases.date) < 21
GROUP BY releases.id
ORDER BY RAND()
LIMIT 0,".rand(1,10);
and then execute this query.

mysql select records with lowest value

I have a table with
total_price
units
unitname
I want to select the records where total_price/units is the lowest.
How do I perform division in a query AND then select the record with the lowest value?
(I would also like to group by unitname - i.e. in case one is ounces and one is liters)
You just use division in the order by clause:
select *
from t
order by total_price / units
limit 1;
Just to be safe -- in the event that units is 0 -- you could do:
select *
from t
where units <> 0
order by total_price / units
limit 1;
If you want this by unit_name then you want to use min():
select unit_name, min(total_price / units)
from t
group by unit_name