Sql Query to retrieve data using table - mysql

I need query to get the count of participants in each level.
Note: participant who is in level 4 should not be in other levels ex: Level 3,2,1. I.e. I'm only interested in the highest level of each participant.
Table :
+----+-------+----------+
| ID | Level | Date |
+----+-------+----------+
| 38 | 1 | 06 -05 |
| 38 | 2 | 08 -05 |
| 38 | 3 | 12 -05 |
| 38 | 4 | 13 -05 |
| 39 | 1 | 13 -05 |
| 39 | 2 | 13 -05 |
| 40 | 1 | 12 -05 |
+----+-------+----------+
Needed Output:
+-------+-------+
| Count | Level |
+-------+-------+
| 1 | 1 |
| 1 | 2 |
| 0 | 3 |
| 1 | 4 |
+-------+-------+

Try this:
SELECT count(t2.Id) as count,t1.Level as level
FROM table1 t1
LEFT JOIN
(SELECT Id,MAX(Level) as Level
FROM table1
GROUP BY Id ) t2 on t1.Id=t2.Id and t1.Level=t2.Level
GROUP BY t1.Level
You can test it on SQL Fiddle

I think you're looking for
Select Count(*), Level FROM table_name GROUP BY Level

the expected result is to know how many people have a level as max level, grouping by level.
SELECT count(id) as count, level
FROM
(
SELECT id, max(level) as level
FROM myTable
GROUP BY id
) t1
GROUP BY level;

Related

Selecting rows that are not defined

How to select rows which are not defined? Like row 2 have undefined day 3 and row 3 have undefined day 1. I want them to be 0 in result set.
+----+-----+-------+
| id | day | count |
+----+-----+-------+
| 1 | 1 | 262 |
| 1 | 2 | 685 |
| 1 | 3 | 984 |
| 2 | 1 | 692 |
| 2 | 2 | 962 |
| 3 | 2 | 355 |
| 3 | 3 | 741 |
+----+-----+-------+
EDIT:
I want select count from days 1, 2 and 3 (not whole table) and display 0 on undefined day.
We can get all unique id values in a Derived Table.
For day, you seem to want only 1,2 and 3 only. So we can directly consider these values only using UNION ALL.
CROSS JOIN between them to get all possible combinations.
LEFT JOIN from all_combinations table to the main table on id and day.
We can use Coalesce() function to consider 0 value for count, for the cases where there is no matching row in the main table
Try the following:
SELECT all_combinations.id,
all_combinations.day,
COALESCE(t.count, 0) AS count
FROM
(
SELECT ids.id, days.day
FROM
(SELECT DISTINCT id FROM your_table) AS ids
CROSS JOIN
(SELECT 1 AS day UNION ALL SELECT 2 UNION ALL SELECT 3) AS days
) AS all_combinations
LEFT JOIN your_table AS t
ON t.id = all_combinations.id AND
t.day = all_combinations.day
Result:
| id | day | count |
| --- | --- | ----- |
| 1 | 1 | 262 |
| 2 | 1 | 692 |
| 3 | 1 | 0 |
| 1 | 2 | 685 |
| 2 | 2 | 962 |
| 3 | 2 | 355 |
| 1 | 3 | 984 |
| 2 | 3 | 0 |
| 3 | 3 | 741 |
View on DB Fiddle

How to get max value with various conditions from a single MySQL table

I have table with a bunch of (machine id) mid's and (sensor id) sid's, and their corresponding (values) v's. Needless to say the id column is a unique row number. (NB: There are other columns in the table, and not all mid's have the same sid's)
Current Table:
+------+-------+-------+-----+---------------------+
| id | mid | sid | v | timestamp |
+------+-------+-------+-----+---------------------+
| 51 | 10 | 1 | 40 | 2015/5/1 11:56:01 |
| 52 | 10 | 2 | 39 | 2015/5/1 11:56:25 |
| 53 | 10 | 2 | 40 | 2015/5/1 11:56:42 |
| 54 | 11 | 1 | 50 | 2015/5/1 11:57:52 |
| 55 | 11 | 2 | 18 | 2015/5/1 11:58:41 |
| 56 | 11 | 2 | 19 | 2015/5/1 11:58:59 |
| 57 | 11 | 3 | 58 | 2015/5/1 11:59:01 |
| 58 | 11 | 3 | 65 | 2015/5/1 11:59:29 |
+------+-------+-------+-----+---------------------+
Q: How would I get the MAX(v)for each sid for each mid?
Expected Output:
+------+-------+-------+-----+---------------------+
| id | mid | sid | v | timestamp |
+------+-------+-------+-----+---------------------+
| 51 | 10 | 1 | 40 | 2015/5/1 11:56:01 |
| 53 | 10 | 2 | 40 | 2015/5/1 11:56:42 |
| 54 | 11 | 1 | 50 | 2015/5/1 11:57:52 |
| 56 | 11 | 2 | 19 | 2015/5/1 11:58:59 |
| 58 | 11 | 3 | 65 | 2015/5/1 11:59:29 |
+------+-------+-------+-----+---------------------+
The expected output is to obtain the whole row with all the (single) max value for all the sids in all the mids.
Addendum:
Due to a very big table, I need to place boundaries with dates. For the sample above the two boundary dates should be 2015/05/01 00:00:00 (1st of May'15) till 2015/05/02 00:00:00 (2nd of May'15). Q: How could I add this date boundary?
Find the max v in subquery for each combination of mid, sid and then join it with your original table to get the desired result.
select *
from your_table t
join (
select mid, sid, max(v) as v
from your_table
group by mid, sid
) t2 using (mid, sid, v);
Note here that if there are multiple rows with same sid, mid and v, it will return all of them.
As mentioned in the comments, since you have an id column, you can include that in limited correlated query like this:
select *
from your_table t1
where id = (select id
from your_table t2
where t1.mid = t2.mid
and t1.sid = t2.sid
order by v desc, id desc
limit 1
);
This will give you one single row per mid, sid combination with max v (and latest id in case of ties).
Use MAX() function with GROUP BY clause
SELECT id, mid, sid, MAX(v) AS v, `timestamp`
FROM MyTable
GROUP BY mid, sid;
This returns rows with maximum values of v for each combination of mid and sid.

Get MAX row for GROUP in MySQL

I have the following data:
+---------+----------+----------+--------+
| id | someId | number | data |
+---------+----------+----------+--------+
| 27 | 123 | 1 | abcde1 |
| 28 | 123 | 3 | abcde2 |
| 29 | 123 | 1 | abcde3 |
| 30 | 123 | 5 | abcde4 |
| 31 | 124 | 4 | abcde1 |
| 32 | 124 | 8 | abcde2 |
| 33 | 124 | 1 | abcde3 |
| 34 | 124 | 2 | abcde4 |
| 35 | 123 | 16 | abcde1 |
| 245 | 123 | 3 | abcde2 |
| 250 | 125 | 0 | abcde3 |
| 251 | 125 | 1 | abcde4 |
| 252 | 125 | 7 | abcde1 |
| 264 | 125 | 0 | abcde2 |
| 294 | 123 | 0 | abcde3 |
| 295 | 126 | 0 | abcde4 |
| 296 | 126 | 0 | abcde1 |
| 376 | 126 | 0 | abcde2 |
+---------+----------+----------+--------+
And I want to get a MySQL query that gets me the data of the row with the highest number for each someId. Note that id is unique, but number isn't
SELECT someid, highest_number, data
FROM test_1
INNER JOIN (SELECT someid sid, max(number) highest_number
FROM test_1
GROUP BY someid) t
ON (someid=sid and number=highest_number)
Unfortunately it is not look quite efficient. In Oracle it could be possible to user OVER clause without subqueries, but MySQL…
Update 1
If there are several instances of highest number this will returs also several data for each pair of someid and number.
To get the only row per each someid we should preaggregate the source table to make someid and number pairs unique (see t1 subquery)
SELECT someid, highest_number, data
FROM
(SELECT someid, number, MIN(data) data
FROM test_1
GROUP BY
someid, number) t1
INNER JOIN
(SELECT someid sid, max(number) highest_number
FROM test_1
GROUP BY someid) t2
ON (someid=sid and number=highest_number)
Update 2
It is possible to simplify previous solution
SELECT someid,highest_nuimber,
(select min(data)
from test_1
where someid=t1.someid and number=highest_nuimber)
FROM
(SELECT someid, max(number) highest_nuimber
FROM test_1
GROUP BY someid) t1
If we materialize unique pairs of someid and number than it is possible to use correlated subquery. Unlike a JOIN it would not produce additional rows if highest value of number is repeated several times.
Slight tweak to Naeel's answer but to return just a single data result for any someId even if there's a tie you should add a GROUP BY:
SELECT t1.someid, t1.number, t1.data
FROM Table1 t1
INNER JOIN (SELECT someId sid, max(number) max_number
FROM Table1
GROUP BY someId) t2
ON (someId = sid AND number = max_number)
GROUP BY t1.someId
SQL Fiddle here

MySQL delete based on single criteria

I'm not sure how to phrase my question and therefore I struggled to find any answer. My data looks something like this:
+------+-------+------------+----+
| id | block | repetition | x |
+------+-------+------------+----+
| 5223 | 1 | 1 | 15 |
| 5223 | 1 | 2 | 17 |
| 5223 | 1 | 3 | 16 |
| 5223 | 2 | 1 | 14 |
| 5223 | 2 | 2 | 15 |
| 6238 | 2 | 1 | 18 |
| 6238 | 2 | 2 | 20 |
| 6238 | 2 | 3 | 20 |
| 6238 | 2 | 4 | 21 |
+------+-------+------------+----+
I would like to query the table to delete the entire block (column) if I detect x < than 15 (just an example). In this example it should delete rows 4 and 5.
delete t1
from your_table t1
inner join
(
select id, block
from your_table
group by id, block
having sum(x < 15) > 0
) t2 on t1.id = t2.id and t1.block = t2.block
You can use a self-join to extract the data you want to delete. When using the same table twice in a query you need to use alias names to distinguish the tables from each other. That is why I used the t1 and t2 alias names.
By joining, the result (that will be deleted) will only be the records that match the inner join.
SQLFiddle demo

How to hidden / delete data in row if same from the top

I have table transaction from mysql query like this.
____________________________________________________________
| id | noskom | nonpbm | noskop | npbp |
|____|_____________|____________|_____________|_____________|
| 1 | 001 | 10 | 20 | 20 |
| 2 | 001 | 20 | 10 | 20 |
| 3 | 002 | 5 | 10 | 20 |
| 4 | 003 | 30 | 5 | 20 |
|____|_____________|____________|_____________|_____________|
and i want result
select sum(nonpbm),sum(noskop),sum(npbp) from transaction group by noskom
____________________________________________________________
| id | noskom | nonpbm | noskop | npbp |
|____|_____________|____________|_____________|_____________|
| 1 | 001 | 30 | 30 | 40 |
| 2 | | | | |
| 3 | 002 | 5 | 10 | 20 |
| 4 | 003 | 30 | 5 | 20 |
|____|_____________|____________|_____________|_____________|
what is mysql query
SELECT
noskom ,
SUM(nonpbm) as nonpbm ,
sum(noskop) as noskop ,
sum(npbp) as npbp
FROM mytable
GROUP BY noskom
If you want to list the IDs of all the rows that contributed to the aggregated values, you can also add this column:
GROUP_CONCAT(id ORDER BY id) AS id
This will give you a comma-separated list of IDs. You can specify a different separator, like EOL:
GROUP_CONCAT(id ORDER BY id SEPARATOR '\r\n') AS id
'\r\n' is the standard line separator in the Windows world. Change to just '\n' or '\r' if you are on a different platform.
select transaction.id,t.noskom,t.sum_nonpbm,t.sum_noskop,t.sum_npbp
from transaction
left join
(
select noskom, min(id) min_id,
sum(nonpbm) sum_nonpbm,
sum(noskop) sum_noskop,
sum(npbp) sum_npbp
from transaction
group by noskom
) t on (transaction.id=t.min_id)
order by transaction.id
Try this query ::
select tbl2.id,tbl1.noskom,tbl1.sum1,tbl1.sum2,tbl1.sum3 from
(select id,noskom,sum(nonpbm) sum1,sum(noskop) sum2,sum(npbp) sum3 from tbl group by noskom) tbl1
right join
(select id,null a,null b,null c,null d
from tbl) tbl2
on tbl1.id = tbl2.id
order by 1 ;