SQL Count Values From the Top 6 - mysql

i trying to create an SQL query to count how many times [Over]='Y' in the Top 6 selection and i receive an error in the merge query.
Query to get Top 6:
SELECT TOP 6 [Number]
,[Over]
,[Goal]
FROM [Test_Hermes].[dbo].[Test]
ORDER BY Number desc
Query to count:
SELECT COUNT([Over])
FROM [dbo].[Test]
WHERE [OVER] = 'Y';
Merge both queries:
SELECT COUNT([Over])
FROM (SELECT TOP 6 [Number]
,[Over]
,[Goal]
FROM [Test_Hermes].[dbo].[Test]
ORDER BY Number desc)
WHERE [OVER] = 'Y';
any help will be appreciate!
Thanks

Show this sample pls.
SELECT
[Number]
,[Over]
,[Goal]
, SUM( If(OVER= 'Y',1,0)) AS CNT
FROM [Test_Hermes].[dbo].[Test]
ORDER BY Number desc
LIMIT 1,6;

You can not use an order by in a sub query.
SELECT COUNT([t1].[Over])
FROM (SELECT TOP 6 [Number]
,[Over]
,[Goal]
FROM [Test_Hermes].[dbo].[Test]) as t1
WHERE [OVER] = 'Y' ;
If you need the order to determine the top 6 use ROW_NUMBER()
SELECT COUNT([t1].[Over])
FROM (SELECT ROW_NUMBER() OVER(PARTITION BY [Number] ORDER BY [Number] DESC) as 'Rank'
,[Number]
,[Over]
,[Goal]
FROM [Test_Hermes].[dbo].[Test]) as t1
WHERE [t1].[OVER] = 'Y' AND [t1].[Rank] <= 6;

Related

get the most common value for each column

I'm attempting to create an SQL query that retrieves the total_cost for every row in a table. Alongside that, I also need to collect the most dominant value for both columnA and columnB, with their respective values.
For example, with the following table contents:
cost
columnA
columnB
target
250
Foo
Bar
XYZ
200
Foo
Bar
XYZ
150
Bar
Bar
ABC
250
Foo
Bar
ABC
The result would need to be:
total_cost
columnA_dominant
columnB_dominant
columnA_value
columnB_value
850
Foo
Bar
250
400
Now I can get as far as calculating the total cost - that's no issue. I can also get the most dominant value for columnA using this answer. But after this, I'm not sure how to also get the dominant value for columnB and the values too.
This is my current SQL:
SELECT
SUM(`cost`) AS `total_cost`,
COUNT(`columnA`) AS `columnA_dominant`
FROM `table`
GROUP BY `columnA_dominant`
ORDER BY `columnA_dominant` DESC
WHERE `target` = "ABC"
UPDATE: Thanks to #Barmar for the idea of using a subquery, I managed to get the dominant values for columnA and columnB:
SELECT
-- Retrieve total cost.
SUM(`cost`) AS `total_cost`,
-- Get dominant values.
(
SELECT `columnA`
FROM `table`
GROUP BY `columnA`
ORDER BY COUNT(*) DESC
LIMIT 1
) AS `columnA_dominant`,
(
SELECT `columnB`
FROM `table`
GROUP BY `columnB`
ORDER BY COUNT(*) DESC
LIMIT 1
) AS `columnB_dominant`
FROM `table`
WHERE `target` = "XYZ"
However, I'm still having issues figuring out how to calculate the respective values.
You might get close, if we want to get percentage values we can try to add COUNT(*) at subquery to get max count by columnA and columnB then do division by total count
SELECT
SUM(cost),
(
SELECT tt.columnA
FROM T tt
GROUP BY tt.columnA
ORDER BY COUNT(*) DESC
LIMIT 1
) AS columnA_dominant,
(
SELECT tt.columnB
FROM T tt
GROUP BY tt.columnB
ORDER BY COUNT(*) DESC
LIMIT 1
) AS columnB_dominant,
(
SELECT COUNT(*)
FROM T tt
GROUP BY tt.columnA
ORDER BY COUNT(*) DESC
LIMIT 1
) / COUNT(*) AS columnA_percentage,
(
SELECT COUNT(*)
FROM T tt
GROUP BY tt.columnB
ORDER BY COUNT(*) DESC
LIMIT 1
) / COUNT(*) AS columnB_percentage
FROM T t1
If your MySQL version supports the window function, there is another way which reduce table scan might get better performance than a correlated subquery
SELECT SUM(cost) OVER(),
FIRST_VALUE(columnA) OVER (ORDER BY counter1 DESC) columnA_dominant,
FIRST_VALUE(columnB) OVER (ORDER BY counter2 DESC) columnB_dominant,
FIRST_VALUE(counter1) OVER (ORDER BY counter1 DESC) / COUNT(*) OVER() columnA_percentage,
FIRST_VALUE(counter2) OVER (ORDER BY counter2 DESC) / COUNT(*) OVER() columnB_percentage
FROM (
SELECT *,
COUNT(*) OVER (PARTITION BY columnA) counter1,
COUNT(*) OVER (PARTITION BY columnB) counter2
FROM T
) t1
LIMIT 1
sqlfiddle
try this query
select sum(cost) as total_cost,p.columnA,q.columnB,p.columnA_percentage,q.columnB_percentage
from get_common,(
select top 1 columnA,columnA_percentage
from(
select columnA,count(columnA) as count_columnA,cast(count(columnA) as float)/(select count(columnA) from get_common) as columnA_percentage
from get_common
group by columnA)s
order by count_columnA desc
)p,
(select top 1 columnB,columnB_percentage
from (
select columnB,count(columnB) as count_columnB, cast(count(columnB) as float)/(select count(columnB) from get_common) as columnB_percentage
from get_common
group by columnB) t
order by count_columnB desc)q
group by p.columnA,q.columnB,p.columnA_percentage,q.columnB_percentage
so if you want to get the percent and dominant value you must make their own query like this
select top 1 columnA,columnA_percentage
from(
select columnA,count(columnA) as count_columnA,cast(count(columnA) as float)/(select count(columnA) from get_common) as columnA_percentage
from get_common
group by columnA)s
order by count_columnA desc
then you can join with the sum query to get all value you want
hope this can help you

Getting the latest row from status

Supposed I have a table with the following rows
test_no
test_count_no
test_status
test_run_no
1
0
STOP
1
2
66
FINISH
1
3
67
FINISH
1
4
0
STOP
2
5
0
STOP
2
I need to get the row which has a test_status of FINISH and has the latest test_no,
for example test_run_no=1 since there is two test_status of FINISH, I only need to get the latest test_no which is 3
In case of test_run_no=2 since there is no test_status=FINISH i only need to return the first row.
The result will be:
test_no
test_count_no
test_status
test_run_no
3
67
FINISH
1
4
0
STOP
2
My current query is
SELECT MAX(test_table.test_run_no)
FROM test_table
WHERE test_table.run_status = 'FINISH'
GROUP BY test_table.test_no
Any idea on what query should I add in order to achieve the result ?
A correlated subquery fits this:
select t.*
from test_table t
where t.test_no = (select t2.test_no
from test_table t2
where t2.test_run_no = t.test_run_no
order by (test_status = 'FINISH') desc,
(case when test_status = 'FINISH' then test_no end) desc,
test_no asc
);
The order by has three keys for your conditions:
Put 'FINISH' first.
For 'FINISH' get the largest test_no.
For others, get the smallest.
This logic can also be expressed using row_number():
select t.*
from (select t.*,
row_number() over (partition by test_run_no
order by (test_status = 'FINISH') desc,
(case when test_status = 'FINISH' then test_no end) desc,
test_no asc
) as seqnum
from test_table t
) t
where seqnum = 1;
What about the following statement:
select * from test t where t.test_status = 'FINISH'
and t.test_no = (select max(t1.test_no) from test t1
where t1.test_run_no = t.test_run_no)
union
select * from test t where t.test_status = 'STOP'
and not exists (select 1 from test t2 where t2.test_run_no = t.test_run_no
and t2.test_status = 'FINISH')
and t.test_no = (select min(test_no) from test t1
where t1.test_run_no = t.test_run_no);
It consists of two SELECT parts. In the first part, for the tests that have a FINISH status, the one with the highest test number is selected.
The second part selects the smallest test number for the tests for which there is no run with the status FINISH.
Is this what you are looking for
SELECT MAX(test_table.test_run_no) FROM test_table
where test_table.run_status = 'FINISH' and test_run_no=1
GROUP BY test_table.test_no
IF ##ROWCOUNT = 0
BEGIN
select MAX(test_table.test_run_no) from test_table GROUP BY test_table.test_no
END
try it :
select * from Table_3 where Table_3.test_count_no = (
select max(test_count_no) from Table_3
) and Table_3.test_status = 'FINISH' and Table_3.test_run_no = 1
union all
select x.test_no, x.test_count_no, x.test_status, x.test_run_no from
(select ROW_NUMBER() over (order by Table_3.test_run_no) as rownum, Table_3.* from Table_3 where Table_3.test_run_no = 2) as x where x.rownum = 1
Use order by desc and use limit 1 to get the exact row.
Like this
SELECT *
FROM test_table
WHERE test_table.test_status = 'FINISH'
ORDER BY test_no desc
LIMIT 1
if you need all the rows
SELECT *
FROM test_table
WHERE test_table.test_status = 'FINISH'
ORDER BY test_no desc
if you need test_no only
SELECT test_table.test_no
FROM test_table
WHERE test_table.test_status = 'FINISH'
ORDER BY test_no desc
LIMIT 1

How to get Last and Secondlast Record from mysql table

From the above image i have n number of records with cat_id and sub_cat_id but in image only two are there.
so i want get the last and secondlast score_in_per value as named lastScore and latetsScore..
how can i retrieve that..?
SELECT
(SELECT score_in_per FROM tbl_student_skill_score ORDER BY date DESC LIMIT 2,0) as lastScore,
(SELECT score_in_per FROM tbl_student_skill_score ORDER BY date DESC LIMIT 1) as latetsScore
i am new to this complicated mysql logics..This what i have tried..
Example:
lets say one user email is inststudent#yopmail.com take the same test 2 times and the test is linked up with one category and sub category.
so the user will take the test any number of times...
from that records i want to get the last two records percentage.
If I understand you correctly; you want to select the two most recent results of a specific type of test taken by a specific student.
You don't use the LIMIT clause correctly. This is the correct syntax: LIMIT {[offset,] row_count | row_count OFFSET offset}. Also, you completely left out the where clause.
So the query should be:
SELECT
(SELECT score_in_per FROM tbl_student_skill_score
WHERE user_email = "email of the user you are interested in"
AND cat_id = categoryOfTestOfInterest
AND sub_cat_id = subcategoryOfTestOfInterest
ORDER BY date DESC LIMIT 1, 1
)AS lastScore,
(SELECT score_in_per FROM tbl_student_skill_score
WHERE user_email = "email of the user you are interested in"
AND cat_id = categoryOfTestOfInterest
AND sub_cat_id = subcategoryOfTestOfInterest
ORDER BY date DESC LIMIT 1
)AS latetsScore;
If a student can take the test multiple times a day (like your image suggests) than you should also order by id (supposing that the id is always greater for newer results) or better still, only by the id:
SELECT
(SELECT score_in_per FROM tbl_student_skill_score
WHERE user_email = "email of the user you are interested in"
AND cat_id = categoryOfTestOfInterest
AND sub_cat_id = subcategoryOfTestOfInterest
ORDER BY id DESC LIMIT 1, 1
)AS lastScore,
(SELECT score_in_per FROM tbl_student_skill_score
WHERE user_email = "email of the user you are interested in"
AND cat_id = categoryOfTestOfInterest
AND sub_cat_id = subcategoryOfTestOfInterest
ORDER BY id DESC LIMIT 1
)AS latetsScore;
One of the way of solving this problem is by using Partition By .
Step1: I have ranked the data for distinct cat_id and sub_cat_id in descending order of date by partition by.
Step2: I have used rank1 which is the latest score and merged it with rank2 which is the second last score
with chck as
(select
cat_id,sub_cat_id,score_in_per,date1,
row_number() over(partition by cat_id,sub_cat_id order by
cat_id,sub_cat_id,date1 desc) as row_num
from tbl)
select a.*,b.second_last_score from
(select cat_id,sub_cat_id,score_in_per,date1,row_num as last_score from chck where row_num=1) a
left join
(select cat_id,sub_cat_id,score_in_per,date1,row_num as second_last_score from chck where row_num=2) b
on a.cat_id = b.cat_id and a.sub_cat_id = b.sub_cat_id;
Let me know in case of any query.
SELECT
( SELECT score_in_per FROM tbl_student_skill_score WHERE cat_id=1 and sub_cat_id=5 ORDER BY date,id DESC LIMIT 1 ) AS latestScore,
( SELECT score_in_per FROM tbl_student_skill_score WHERE cat_id=1 and sub_cat_id=5 ORDER BY date,id DESC LIMIT 1,1 ) AS lastScore

How to write sql query to get items from range

I would like to get values without the smallest and the biggest ones, so without entry with 2 and 29 in column NumberOfRepeating.
My query is:
SELECT Note, COUNT(*) as 'NumberOfRepeating'
WHERE COUNT(*) <> MAX(COUNT(*))AND COUNT(*) <> MIN(COUNT(*))
FROM Note GROUP BY Note;
SELECT Note, COUNT(*) as 'NumberOfRepeating'
FROM Notes
GROUP BY Note
HAVING count(*) <
(
SELECT max(t.maxi)
FROM (select
Note, COUNT(Note) maxi FROM Notes
GROUP BY Note
) as t
)
AND
count(*) >
(
SELECT min(t.min)
FROM (select
Note, COUNT(Note) min FROM Notes
GROUP BY Note
) as t
)
try this code.
One method would use order by and limit, twice:
select t.*
from (select t.*
from t
order by NumberOfRepeating asc
limit 99999999 offset 1
) t
order by NumberOfRepeating desc
limit 99999999 offset 1;
Try this code,
Select * from Note where NumberOfRepeating < (select MAX(NumberOfRepeating) from Note ) AND NumberOfRepeating > (select MIN(NumberOfRepeating) from Note );
Here in the code, as in your table Note is the name of the table, and NumberOfRepeating is the column name, as in your table.
Try this. It should work
SELECT *
FROM ( SELECT Note, COUNT(*) as 'NumberOfRepeating'
FROM Notes
GROUP BY Note
ORDER BY NumberOfRepeating DESC
LIMIT 1, 2147483647
) T1
ORDER BY T1.NumberOfRepeating
LIMIT 1, 2147483647

SQL SCORE RANKING

I'm working with score ranking on my app for all user score. My problem is I don't know how to return one row for each stud_num.
My query:
SELECT * FROM score WHERE assess_type = 'professional' ORDER BY total_score DESC.
Result:
As you can see I have 3 stud_num and I only want one row per stud_num and the highest score of it.
You can use correlated query like this:
SELECT * FROM score t
WHERE t.assess_type = 'professional'
AND t.total_score = (select max(s.total_score)
from score s
where t.stud_num = s.stud_num)
group by stud_num
The option given by #sagi is good:
SELECT * FROM score t
WHERE t.assess_type = 'professional'
AND t.total_score = (select max(s.total_score)
from score s
where t.stud_num = s.stud_num)
group by stud_num
Another option would be to use an inner join and group by together.
The resulting query would become:
select * from score a
inner join (
SELECT stud_num, max(total_score) tscore FROM `score` group by stud_num) b
on a.stud_num = b.stud_num and total_score= tscore
group by a.stud_num
try it out at sqlfiddle
Use the MAX and GROUP BY functions like this:
SELECT score_id, stud_num, assess_type, total_item, MAX(total_score), average, date_taken
FROM score
WHERE assess_type = 'professional'
GROUP BY stud_num
ORDER BY 5 DESC
Here's my the ans:
SELECT score_id, stud_num, assess_type, total_item, MAX( total_score )
FROM score
WHERE assess_type = 'professional'
GROUP BY stud_num, total_item
ORDER BY MAX( total_score ) DESC