SELECT * FROM combination in MySQL - mysql

This is my MySQL databse:
+-----+------------+----------+----------------+--------------+-----------------+
| id | data | hora | conexoes_total | conexoes_sim | conexoes_lentas |
+-----+------------+----------+----------------+--------------+-----------------+
| 1 | 2013-11-18 | 00:00:02 | 200 | 1 | 30 |
| 2 | 2013-11-18 | 10:15:03 | 14 | 2 | 25 |
| 3 | 2013-11-18 | 10:30:03 | 53 | 3 | 25 |
| 4 | 2013-11-18 | 10:45:02 | 60 | 5 | 26 |
| 5 | 2013-11-18 | 11:00:02 | 66 | 3 | 27 |
| 6 | 2013-11-18 | 11:15:03 | 74 | 5 | 27 |
.
.
.
I want select * from every 00:00:% data and the last value inserted..
I already know how to select the midnight values: SELECT * FROM audiencia WHERE hora LIKE '00:00:%';, and this what i got:
+-----+------------+----------+----------------+--------------+-----------------+
| id | data | hora | conexoes_total | conexoes_sim | conexoes_lentas |
+-----+------------+----------+----------------+--------------+-----------------+
| 1 | 2013-11-18 | 00:00:02 | 200 | 1 | 30 |
| 57 | 2013-11-19 | 00:00:02 | 446 | 1 | 97 |
| 153 | 2013-11-20 | 00:00:02 | 300 | 3 | 173 |
| 349 | 2013-11-21 | 00:00:02 | 42 | 2 | 94 |
+-----+------------+----------+----------------+--------------+-----------------+
But now i want to show the last value inserted in table together with the above result..
How can i manage a command to do that to me?

(SELECT * FROM audiencia WHERE hora LIKE '00:00:%')
UNION
(SELECT * FROM audiencia ORDER BY id DESC LIMIT 1);

Do you want to fetch the last value inserted for column hora of table audiencia which starts from 00:00: ?
If Answer to the above question is YES, then the below SQL will solve your problem.
SELECT * FROM audiencia WHERE hora LIKE '00:00:%' ORDER BY id DESC LIMIT 1;
In case the answer to the above question is NO, then I might have not understood the requirement properly. Kindly, please explain the requirement.
Thanks,
Abhijit

Related

MYSQL adding columns value of rows

I have a problem in which I have a STUDENT table as
+-------------+-------------+-------------+-------------+---------------+
| roll_number | name | subject_one | subject_two | subject_three |
+-------------+-------------+-------------+-------------+---------------+
| 1 | Sheila | 32 | 48 | 64 |
| 2 | Rachel | 24 | 21 | 25 |
| 3 | Christopher | 55 | 12 | 10 |
+-------------+-------------+-------------+-------------+---------------+
I want the print the output as
+-------------+-------------+-------------+
| roll_number | name | total |
+-------------+-------------+-------------+
| 1 | Sheila | 144|
| 2 | Rachel | 70 |
| 3 | Christopher | 77 |
+-------------+-------------+-------------+
and select all student having marks greater than 75 ??
How can I achieve this using MYSQL ??
I think you just need the aggregate functions and using them is enough. I am not sure if it can help you or not.
SELECT roll_number , name , (subject_one + subject_two + subject_three) AS total FROM STUDENT HAVING total > 75 ;

Where and group conflict?

I have a table like this:
mysql> select * from studentscore;
+------------+-----------+-------+
| student_id | cource_id | score |
+------------+-----------+-------+
| 1 | 1 | 80 |
| 1 | 2 | 90 |
| 1 | 3 | 85 |
| 1 | 4 | 78 |
| 2 | 2 | 53 |
| 2 | 3 | 77 |
| 2 | 5 | 80 |
| 3 | 1 | 71 |
| 3 | 2 | 70 |
| 3 | 4 | 80 |
| 3 | 5 | 65 |
| 3 | 6 | 75 |
| 4 | 2 | 90 |
| 4 | 3 | 80 |
| 4 | 4 | 70 |
| 4 | 6 | 95 |
| 5 | 1 | 60 |
| 5 | 2 | 70 |
| 5 | 5 | 80 |
| 5 | 6 | 69 |
| 6 | 1 | 76 |
| 6 | 2 | 88 |
| 6 | 3 | 87 |
| 7 | 4 | 80 |
| 8 | 2 | 71 |
| 8 | 3 | 58 |
| 8 | 5 | 68 |
| 9 | 2 | 88 |
| 10 | 1 | 77 |
| 10 | 2 | 76 |
| 10 | 3 | 80 |
| 10 | 4 | 85 |
| 10 | 5 | 83 |
| 11 | 3 | 80 |
| 12 | 4 | 99 |
| 13 | 5 | 74 |
+------------+-----------+-------+
I want to show student_id and students' average scores that are higher than 80.
The output I want is like this:
+------------+-------------------+
| student_id | Average |
+------------+-------------------+
| 1 | 83.25 |
| 4 | 83.75 |
| 6 | 83.66666666666667 | // and how can I make this result shorter like 83.67?
| 7 | 80 |
| 9 | 88 |
| 10 | 80.2 |
| 11 | 80 |
| 12 | 99 |
+------------+-------------------+
I've tried the following codes
mysql> select student_id, avg(score) as average_score
-> from studentscore
-> group by student_id
-> where avg(score) >= 80;
and it gave me an syntax error.
I know by rules the where clause should go before the group by clause but I can't because the where clause depends on the result from the group by clause, and if I switch their position it will give me another error("Invalid use of group function").
Can some one tell me how to get the table I want?
use "having" instead of "where"
use having instead of where.
Here's the difference:
with where you can write a predicate that will be applied to each row
with having you can write a predicate that will applied to each group
and in your case, the 2nd is the only solution that can work.
select student_id, avg(score) as average_score
from studentscore
group by student_id
having avg(score) >= 80;
where applies a filter to your data before grouping has taken place, whereas having applies a filter post-grouping. round(,2) will format as you also ask:
select student_id, round(avg(score), 2) as average_score
from studentscore
group by student_id
having average_score >= 80;

SQL One to Many column association rows

Given the table below I want to select the rows for which the same 'CODE' is associated with multiple 'SUB_CODE'.
+------+------------+-------------+
| DIV | CODE | SUB_CODE |
+------+------------+-------------+
| 11 | 1000 | 1212 |
| 11 | 1000 | 1213 |
| 11 | 1000 | 3434 |
| 11 | 1000 | 1000 |
| 11 | 1000 | 3000 |
| 11 | 3000 | 1213 |
| 11 | 2000 | 1212 |
| 20 | 1500 | 5656 |
| 20 | 1500 | 1213 |
+------+------------+-------------+
For the above table the result should be
+------+------------+-------------+
| DIV | CODE | SUB_CODE |
+------+------------+-------------+
| 11 | 1000 | 1212 |
| 11 | 1000 | 1213 |
| 11 | 1000 | 3434 |
| 11 | 1000 | 1000 |
| 11 | 1000 | 3000 |
| 11 | 1500 | 5656 |
| 11 | 1500 | 1213 |
+------+------------+-------------+
This is what I tried, how ever my results fails.
Select CODE from TABLE_NAME where (count(SUB_CODE) > 1);
First fetch the CODEs for which multiple SUB_CODEs exists; then project the table columns filtering using the above results as a nested query:
select * from TABLE_NAME where CODE in
(select CODE from TABLE_NAME group by CODE having count(SUB_CODE) > 1);
demo: http://sqlfiddle.com/#!9/1d91f/3/0
TRY THIS:
Select `DIV`, `CODE`, `SUB_CODE` from TABLE_NAME GROUP BY `SUB_CODE`

MySQL filter by GROUP BY result

I don't know if this is something I can achieve effectively with sub queries, or how to even build a query for this. I have to extract some knowledge about people no longer using our system. Imagine we have 3 users with user id 1024, 1234, and 5678; and User 1024 and 1234 are using theme A, and 5678 is using theme B:
$ SELECT * FROM user; | $ SELECT * FROM user_theme;
+------+------+ | +------+-------+
| id | name | | | user | theme |
+------+------+ | +------+-------+
| 1024 | John | | | 1024 | A |
| 1234 | Jane | | | 1234 | A |
| 5678 | Jeff | | | 5678 | B |
+------+------+ | +------+-------+
The usage tracking table appears as this:
$ SELECT * FROM user_usage;
+----+------+---------------------+------+
| id | user | date | uses |
+----+------+---------------------+------+
| 1 | 1234 | 2014-08-02 00:00:00 | 5 |
| 2 | 1234 | 2014-08-03 00:00:00 | 5 |
| 3 | 1234 | 2014-08-04 00:00:00 | 3 |
| 4 | 1234 | 2014-08-05 00:00:00 | 6 |
| 5 | 1024 | 2014-08-02 00:00:00 | 8 |
| 6 | 1024 | 2014-08-03 00:00:00 | 7 |
| 7 | 1024 | 2014-08-04 00:00:00 | 4 |
| 8 | 1024 | 2014-08-05 00:00:00 | 6 |
| 9 | 1024 | 2014-09-02 00:00:00 | 1 |
| 10 | 1024 | 2014-09-03 00:00:00 | 2 |
| 11 | 1024 | 2014-09-04 00:00:00 | 3 |
| 12 | 1024 | 2014-09-05 00:00:00 | 4 |
| 13 | 5678 | 2014-08-02 00:00:00 | 8 |
| 14 | 5678 | 2014-08-03 00:00:00 | 7 |
| 15 | 5678 | 2014-08-04 00:00:00 | 4 |
| 16 | 5678 | 2014-08-05 00:00:00 | 6 |
| 17 | 5678 | 2014-09-02 00:00:00 | 1 |
| 18 | 5678 | 2014-09-03 00:00:00 | 2 |
| 19 | 5678 | 2014-09-04 00:00:00 | 3 |
| 20 | 5678 | 2014-09-05 00:00:00 | 4 |
+----+------+---------------------+------+
I want to find out the break down to see how many usage have dropped from our system in 2014-09 (aka: have usage data in 2014-08, but no longer in 2014-09), grouped by the theme. So I want to write something like:
SELECT
user_theme.theme,
SUM(user_usage.users) 'uses lost'
FROM
user_theme
LEFT JOIN user_usage
ON user_theme.user = user_usage.user
WHERE
...
GROUP BY
user_theme.theme
# HAVING ...?
And get result such as:
+-------+-----------+
| theme | uses lost |
+-------+-----------+
| A | 19 |
| B | 0 |
+-------+-----------+
Where the 19 comes from SUM(uses) for WHERE user = 1234 AND YEAR(date) = 2014 AND MONTH(date) = 8.
I don't know I care about the SUM(uses) from user = 1234 in advance, because I only know I need to include user 1234 in the SUM(uses)'s WHERE clause because SUM(uses) for WHERE user = 1234 AND YEAR(date) = 2014 AND MONTH(date) = 9 is 0.
There's actually a lot of users, and a handful of themes (around 20K users, and about 10 themes), so ideally, I think I'd like to avoid doing the filtering in code as opposed to directly in the database. Is there a way to do this effectively in MySQL using raw SQL queries?
Here is query which compares current month with previous one:
set #current_month = now();
set #previous_month = date_sub(#current_month, interval 1 month);
set #current_month = concat(year(#current_month), month(#current_month));
set #previous_month = concat(year(#previous_month), month(#previous_month));
select a.`theme`, sum(ifnull(b.uses_lost,0)) as uses_lost
from
`user_theme` as a
left outer join
(
select `user`, sum(uses) as uses_lost
from `user_usage`
where concat(year(`date`), month(`date`)) = #previous_month
and `user` not in (
select `user`
from `user_usage`
where concat(year(`date`), month(`date`)) = #current_month)
group by `user`
) as b
on (a.`user`=b.`user`)
group by a.`theme`;
fiddle for play
main idea is to find all users who used system during last month and has no rows during current month

MySQL query works in Workbench, but not within code

Using MySQL 5.5.30, for a table, purchase_order_product (MyISAM), that has the following records:
+----------+------------------+
| order_id | order_product_id |
+----------+------------------+
| 98 | 1 |
| 99 | 14 |
| 99 | 15 |
| 100 | 16 |
| 100 | 17 |
| 100 | 18 |
| 101 | 19 |
| 102 | 20 |
+----------+------------------+
When I run the following query from MySQL Workbench 5.2.47 CE:
SELECT pop.order_id, pop.order_product_id,
#RUNNING:=IF(#PREVIOUS = pop.order_id, #RUNNING, 0) + 1 AS rownum,
#PREVIOUS:=pop.order_id as previd
FROM purchase_order_product pop
ORDER BY pop.order_id , pop.order_product_id ASC;
I get the following output:
+----------+------------------+--------+--------+
| order_id | order_product_id | rownum | previd |
+----------+------------------+--------+--------+
| 98 | 1 | 1 | 98 |
| 99 | 14 | 1 | 99 |
| 99 | 15 | 2 | 99 |
| 100 | 16 | 1 | 100 |
| 100 | 17 | 2 | 100 |
| 100 | 18 | 3 | 100 |
| 101 | 19 | 1 | 101 |
| 102 | 20 | 1 | 102 |
+----------+------------------+--------+--------+
My desired goal is the value of rownum, which is fine and as expected so far...
HOWEVER, when I run the query from within my PHP code OR from the mysql command line against the same database using the same db user, I get the following output:
+----------+------------------+--------+--------+
| order_id | order_product_id | rownum | previd |
+----------+------------------+--------+--------+
| 98 | 1 | 1 | 98 |
| 99 | 14 | 1 | 99 |
| 99 | 15 | 1 | 99 |
| 100 | 16 | 1 | 100 |
| 100 | 17 | 1 | 100 |
| 100 | 18 | 1 | 100 |
| 101 | 19 | 1 | 101 |
| 102 | 20 | 1 | 102 |
+----------+------------------+--------+--------+
As you can see, rownum is always 1!
I have search extensively for a solution to this perplexing issue, to no avail. Does anyone have any idea what may be going on? Am I doing something wrong?
You need to initialize the variable:
SET #RUNNING:=0;
SET #PREVIOUS:=0;
This must be done before your query and in the same mysql session.