sorting 2 Columns in mysql - mysql

i Have Following Mysql Query
SELECT DISTINCT
main_Table.id,
t1.percentage,
t2.percentage
FROM image_new main_Table
INNER JOIN (SELECT DISTINCT
image_colors_new.image_id,
image_colors_new.percentage
FROM image_colors_new
WHERE image_colors_new.s BETWEEN 80 AND 120 AND image_colors_new.h BETWEEN - 20 AND 20 AND image_colors_new.v BETWEEN 73 AND 103
GROUP BY image_colors_new.percentage
ORDER BY image_colors_new.percentage DESC) t1
ON main_Table.id = t1.image_id
INNER JOIN (SELECT DISTINCT
image_colors_new.image_id,
image_colors_new.percentage
FROM image_colors_new
WHERE image_colors_new.s BETWEEN - 20 AND 20 AND image_colors_new.h BETWEEN - 20 AND 20 AND image_colors_new.v BETWEEN 85 AND 115
GROUP BY image_colors_new.percentage
ORDER BY image_colors_new.percentage DESC) t2
ON main_Table.id = t2.image_id
This Gives me Following Out Put
id percentage percentage1
36888 32.975669099756 0.559610705596
54899 9.9722991689751 0.55401662049861
43584 9.9195710455764 9.3833780160858
61517 9.7938144329897 40.20618556701
78076 9.7267759562842 12.786885245902
52123 9.6916299559471 3.3039647577093
36378 9.5798319327731 18.655462184874
43820 9.5238095238095 10.31746031746
53579 9.4736842105263 5.6140350877193
but i want rows in following format i.e rows that have percentage with highest value must pop to top, from either of columns
id percentage percentage1
61517 9.7938144329897 40.20618556701
36888 32.975669099756 0.559610705596
36378 9.5798319327731 18.655462184874
78076 9.7267759562842 12.786885245902
43820 9.5238095238095 10.31746031746
43584 9.9195710455764 9.3833780160858
54899 9.9722991689751 0.55401662049861
52123 9.6916299559471 3.3039647577093
53579 9.4736842105263 5.6140350877193

It sounds like you want to order by the larger of the percentage values. Add:
order by greatest(t1.percentage, t2.percentage) desc;
This should actually go in the outer query. Don't get in the habit of doing order by in subqueries. It might usually work, but there are no guarantees (and this is particularly true in other databases in multi-threaded implementations).

Related

Alternative Using Having in mysql

I am trying to get the records where avg is greater than 81, I noticed I can't use a simple where avg(score) > 80
But using a Having statement is problematic as well as it does not consider where the individual records average is greater than 80, but it considers the group average. Is there an alternative?
In general, if we want to return aggregates (SUM,AVG) and also return detail that makes up the aggregate, we typically use two SELECT
As a rudimentary example, consider a table of "test_score"
test_id student_id score
------- ---------- -----
101 6 90
101 7 71
101 8 88
222 6 93
222 7 78
222 8 81
We can calculate the average score for each test, with a SELECT ... GROUP BY query.
SELECT r.test_id AS test_id
, AVG(r.score) AS avg_score
, MAX(r.score) AS high_score
FROM test_score r
GROUP
BY r.test_id
We expect that to return a resultset like this:
test_id avg_score
------- ---------
101 83
222 84
We can use that query as an inline view i.e. we wrap it in parens and reference it like a table in the FROM clause of another SELECT.
As a demonstration, to return student scores that were better (or equal to) average for each test:
SELECT s.test_id
, s.avg_score
, t.student_id
, t.score
FROM ( -- inline view to get average score for each test_id
SELECT r.test_id AS test_id
, AVG(r.score) AS avg_score
FROM test_score r
GROUP
BY r.test_id
) s
LEFT
JOIN test_score t
ON t.test_id = s.test_id
AND t.score >= s.avg_score
ORDER
BY t.test_id
, s.score DESC
And we'd expect that to return something like:
test_id avg_score student_id score
------- --------- ---------- -----
101 83 6 90
101 83 8 88
222 84 6 93
The first two columns, returned from the inline view, are the result of the aggregate (AVG). The last two columns are detail rows, matched to the rows from the aggregate result.
To summarize the main point here:
To return aggregates along with details, we typically need two SELECT.
One SELECT to get the aggregates (with a GROUP BY if the aggregates are "per" each something or other)
Another SELECT to get the details and a match to the aggregate.
If the average score being computed in your query is already correct, you are just having trouble filtering by it, just wrap it in parens and select from it
select * from (
SELECT Count(entry_id) AS Filled,
q.question AS Questions,
AVG(ag.score) AS TOTAL
FROM entry e
LEFT JOIN entry_answer ea
ON ea.entry_id= e.entry
LEFT JOIN question q
ON q.question_id = ea.question_id
LEFT JOIN question_group qg
ON ea.question_parent_id = qg.question_parent_id
LEFT JOIN answer_group ag
ON ag.question_id = qg.question_parent_id
JOIN sent_list using (sent_list_id)
WHERE
entry_group_id = 2427
AND ag.score >= 0
AND ea.rated_answer_id = ag.rated_answer_id
AND sent_id = 6156
AND e.entry_date BETWEEN '2018-01-01' AND '2019-12-31'
group by ea.question_id
) results where total >= 81

Equals values with the last limited row

I use a limit query to get a list of the top 5 directors counting also the total of their works e.g.
a 137
b 120
c 90
d 76
e 52
It really works but what about if with the last row there are also some names with equal works. And it usally happens...
f 52
g 52
h 52...
the query is:
SELECT
T_people.person,
COUNT(ID_films) AS CountOfID_films
FROM
((MT_films
JOIN ST_peoplefilms ON ((MT_films.ID_films = ST_peoplefilms.ID_films)))
JOIN T_people ON ((T_people.ID_person = ST_peoplefilms.ID_person)))
GROUP BY T_people.person, T_people.man
HAVING (T_people.man = 1)
ORDER BY COUNT(ST_peoplefilms.ID_films) DESC
LIMIT 5
thank's a lot
Create a subquery that gives the top 5 totals. Then use what you have now (you can remove LIMIT 5 and the ordering) and apply INNER JOIN on the subquery with respect to the totals. That will filter away all non-relevant rows.

Filtering column with aggregated function with itself to show max records

I am having a hard time trying to figure out the best way to filter records against itself using the MAX function.
My desired results are to have my IDs in one column and then the max records from the group by on the next column.
ID Max_id group_id
3000 3004 6
3001 3004 6
3002 3004 6
3003 3004 6
4000 4004 20
4001 4004 20
4000 4001 42
Here is my table structure and sampling data. I can use a min and max function and group by group_id but cannot access the middle ID's when doing this. When I attempt to use just the ID without the min() I get constraint errors.
http://sqlfiddle.com/#!9/40ef34/1
Use a cross join here.
SQL Fiddle
SELECT
g.id, m.maxid,g.group_id
FROM
groups g
cross join (select group_id, max(id) as maxid from groups group by group_id) m
where m.group_id = g.group_id and g.id <> m.maxid

MySql JOIN on most recent start_date?

I have two tables, one with transactions (with date). The other with a percentage and date the percentage it went into effect (assume 00:00:00). The percentage remains in effect until a new percent goes into effect. I need to join on the percentage that was in effect when the transaction happened.
transactions_table
event_date amount
2011-01-01 230
2011-02-18 194
2011-03-22 56
2011-04-30 874
percent_table
effective percent
2010-12-30 15
2011-03-05 25
2011-04-12 30
The result I'm looking for is:
event_date amount percent
2011-01-01 230 15
2011-02-18 194 15
2011-03-22 56 25
2011-04-30 874 30
I've tried:
SELECT t.event_date, t.amount, p.percent
FROM transactions_table AS t
LEFT JOIN percent_table AS p ON t.event_date >= p.effective
ORDER BY `t`.`event_date` DESC LIMIT 0 , 30;
That gives me, seemingly random percentages. It seems to me like I need to get the greatest date >= p.effective, not just any random date >= p.effective.
I tried:
SELECT t.event_date, p.percent
FROM bedic_sixsummits_transactions AS t
LEFT JOIN bedic_sixsummits_percent AS p ON MAX(t.event_date >= p.effective)
ORDER BY `t`.`event_date` DESC LIMIT 0 , 30
but MySQL just laughed at my feeble attempt.
How can I do this?
SELECT t.event_date, t.amount, p.percent
FROM bedic_sixsummits_transactions AS t
LEFT JOIN bedic_sixsummits_percent AS p
ON p.effective =
( SELECT MAX( p2.effective ) FROM bedic_sixsummits_percent AS p2
WHERE p2.effective <= t.event_date
)
ORDER BY t.event_date DESC LIMIT 0 , 30
Even more simpler and with no subquery:
SELECT event_date, amount, MAX(_percent) as _percent
FROM transactions_table
LEFT JOIN percent_table p1 ON event_date >= effective
GROUP BY event_date, amount
ORDER BY event_date;
http://sqlfiddle.com/#!3/e8ca3/17/0
Note that it is possible because of the business model involved. If you wan't to retrieve other fields of the percent_table it won't be appropriate anymore :/

MySQL Max Count without Order By

I have the following MySQL line:
SELECT age, count(*) AS total FROM pacient WHERE age BETWEEN 20 AND 40 GROUP BY age ORDER BY age and I need to add an additional column to it that shows ONLY the max value of the count(*) for every row. For example:
13 2 7
18 2 7
23 5 7
24 7 7
26 6 7
32 3 7
38 1 7
41 1 7
46 4 7
This would be 3 columns and the 3rd column shows 7 since 7 was the highest number in the second column where the count(*) is made.
Here the solution:
select age,
count(*),
(select max(c) from
(select count(*) as c from pacient where age between 20 and 40 group by age) as x) as t
from pacient
where age between 20 and 40
group by age
order by age;
Have you tried to wrap your query with another query? something like
SELECT A.age, A.total, MAX(A.total) as max_value FROM (
SELECT age, count(*) AS total
FROM pacient
WHERE age BETWEEN 20 AND 40
GROUP BY age ORDER BY age) as A
GROUP BY A.age, A.total
select
p.Age,
count(*) CountPerAge,
max(ar.AllRecs) AllRecs
from
pacient p,
( select count(*) AllRecs
from pacient p2
where p2.age between 20 and 40 ) ar
where
p.age between 20 and 40
group by
p.age
By doing a join to the second "subselect" with no join condition, it will give a Cartesian result... Since it is a count with no group by, it will always return a single record and thus be joined to all age rows otherwise. The MAX() of the value is no problem since it is the only record will just be returned as-is.
It is always good to use SQL VIEWS instead of using sub queries. Because VIEW will be having already compiled result.
CREATE VIEW subqueryView
SELECT age, count(*) AS total
FROM pacient
WHERE age BETWEEN 20 AND 40
GROUP BY age ORDER BY age
SELECT A.age, A.total, MAX(A.total) as max_value FROM (SELECT FROM subqueryView) as A
GROUP BY A.age, A.total