MySQL aggregation function to sum the differences from row to row - mysql

i've got this lil' mysql table:
+----+-------+
| id | value |
+----+-------+
| 1 | 1240 |
| 2 | 1022 |
| 3 | 802 |
| .. | .. |
+------+-----+
i'm searching for a sql-query summing up the difference between the rows:
difference of row 1 and 2 + difference of row 2 and 3 + ...
is that possibile with sql?

Sure! Your query will look something like this:
SELECT a.id,
b.VALUE - a.VALUE difference
FROM mytable a
JOIN mytable b
ON b.id = a.id + 1
The idea is to join the table with itself offset by one row -- then you can do math with values that were originally on adjacent rows.

Related

how to get AVG for every record in SQL

I need to get AVG for every row in SQL for example:
this is the first table
+ ---+------+-------------+
| course_id | course_name |
+ ----------+-------------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | g |
+ ---+------+-------------+
This is the second table
I need to get AVG for both id 1 and 2. the result for example:
+ -------------------+------+----------+
| course_feedback_id | rate |course_id |
+ -================--+------+----------+
| 1 | 4 | 1 |
| 2 | 3 | 1 |
| 3 | 2 | 2 |
+ -------------------+------+----------+
this is the final answer that i need
+ ----------------------+
| course_id | AVG(rate) |
+ -=======--+-----------+
| 1 | 3.5 |
| 2 | 2 |
+ ----------------------+
I tried this soulution but it will give me only the first row not all records.
SELECT *, AVG(`rate`) from secondTable
please help
SELECT `id`, AVG(`rate`) FROM `your_table` GROUP BY `id`
Try this:
SELECT c.course_id, AVG(fb.rate)
FROM course AS c
INNER JOIN course_feedback AS fb ON fb.course_id = c.course_id
GROUP BY c.course_id
Select course_id,t2.rate from table1 where course_id,rate in (Select course_id,avg(rate) as rate from table group by course_id t2)
When you have multiple entries/redundant entries and you want to find some aggregation per each as in this case you got id containing redundant records, In such cases always try to use group by as group by as the name says will group records of the column to which it is applied and if you apply aggregation avg in this case will be groupwise column to which it is being applied not as a whole like for id 1 we have 2 redundant entries so itll apply avg(id1_entries)..likewise as a group.

How does this matrix multiply work in SQL?

Full disclosure, I'm a noob at SQL
Given two sparce matrices A and B, defined as:
A(row_number, column_number, value) and B(row_number, column_number, value)
I don't understand how this query represents the multiplication of the two matrices:
SELECT A.row_number, B.column_number, SUM(A.value * B.value)
FROM A, B
WHERE A.column_number = B.row_number
GROUP BY A.row_number, B.column_number
My confusion lies in the SUM syntax and the GROUP BY / SELECT syntax
So for my GROUP BY / SELECT confusion, I don't understand why the expressions
A.row_number and B.column_number are necessary after the SELECT statement
Why do we have to specify that when we're already using SELECT and WHERE ? To me that seems like we're saying we want to SELECT using those expressions (A.row_number and B.column_number) even though we're given back a table from WHERE already. Would it not make more sense to just say SELECT * ? I'm assuming that GROUP BY just requires you to type out the expressions it uses in the SELECT statement, but I don't know for sure.
For the SUM, I just want to clarify, the SUM is only using the A.value and the B.value from whatever is returned by the WHERE correct? Otherwise, you would be multiplying all A.value with all B.value.
Clarifying either of these would be immensely helpful. Thank you!
create table A
( column_number int,
row_number int,
value int
);
create table B
( column_number int,
row_number int,
value int
);
insert A (column_number,row_number,value) values (1,1,1),(1,2,2),(2,1,3),(2,2,4);
insert B (column_number,row_number,value) values (1,1,10),(1,2,20),(2,1,30),(2,2,40);
Data with your old style (non explicit) join without aggregage or group by:
SELECT A.row_number as Ar, B.column_number as Bc,
A.value as Av,B.value as Bv,A.value*B.value as product
FROM A, B
WHERE A.column_number = B.row_number
+------+------+------+------+---------+
| Ar | Bc | Av | Bv | product |
+------+------+------+------+---------+
| 1 | 1 | 1 | 10 | 10 |
| 2 | 1 | 2 | 10 | 20 |
| 1 | 1 | 3 | 20 | 60 |
| 2 | 1 | 4 | 20 | 80 |
| 1 | 2 | 1 | 30 | 30 |
| 2 | 2 | 2 | 30 | 60 |
| 1 | 2 | 3 | 40 | 120 |
| 2 | 2 | 4 | 40 | 160 |
+------+------+------+------+---------+
Seeing the above, the below gets a little more clarity:
SELECT A.row_number, B.column_number,sum(A.value * B.value) as theSum
FROM A, B
WHERE A.column_number = B.row_number
GROUP BY A.row_number, B.column_number
+------------+---------------+--------+
| row_number | column_number | theSum |
+------------+---------------+--------+
| 1 | 1 | 70 |
| 1 | 2 | 150 |
| 2 | 1 | 100 |
| 2 | 2 | 220 |
+------------+---------------+--------+
Giving table name after SELECT will identify which table to refer to. Mainly useful in the case where both tables have same column names.
GROUP BY will aggregate the data and display one record per grouped-by value. That is, in your case, you'll end up with only one record per row-column combination.
By definition multiplication of two matrices A(n,m) and B(m,p) produces a matrix C(n,p).
So the SQL for multiplication should return same data structure as was used for storage of A and B, which is three columns:
row_number
column_number
value
, with one value per (row, column) combination.
This is why you need first two in the group by clause.
WHERE clause is independent from SELECT. First is responsible for getting the right records, second for getting the right columns.

MySQL - how to get count of rows

I have these data in database:
+----+------------+---------+
| id | col1 | col2 |
+----+------------+---------+
| 1 | 3 | 2 |
| 2 | 2 | 3 |
| 3 | 4 | 5 |
+----+------------+---------+
I am trying to do a query, that will give me a count of rows, in which are the same numbers.
I know the value one of them (the numbers).
In this case, the same numbers are 2 and 3 (in the columns col1 and col2) - I am trying to get from database number 2 (two rows). I have available always one of two numbers - in this case number 3.
Is possible to do this query?
Thanks for help.
For the very narrow scenario you specified, I would try this:
select count(*)
from myTable mt1
inner join myTable mt2 on (mt1.col1 = mt2.col2 AND mt2.col1 = mt1.col2)
and mt1.col1 = 3 --here goes the known value
This only works for the data you posted. Please let us know the count for the following scenario:
+----+------------+---------+
| id | col1 | col2 |
+----+------------+---------+
| 1 | 3 | 2 |
| 2 | 2 | 3 |
| 3 | 3 | 2 |
| 4 | 3 | 5 |
| 5 | 4 | 5 |
+----+------------+---------+
Are you looking something like
SELECT (col1+col2) , COUNT(*) AS num_rows
FROM table1
WHERE col1 =3 OR col2 =3
GROUP BY (col1+col2)
HAVING num_rows >1
With this query:
select count(*) count_rows
from table1
where col1=3 or col2=3
group by concat(IF(col1<col2, col1, col2), ',', IF(col1<col2, col2, col1))
you get the result 2.
Replace the 3 from the query in the where clause if there is another input.
The value for concat(IF(col1<col2, col1, col2), ',', IF(col1<col2, col2, col1)) would be "2,3" for records 1-2, (and "4,5" for the third record).

mysql select ordernumber by group

I'm trying to do something like 'select groupwise maximum', but I'm looking for groupwise order number.
so with a table like this
briefs
----------
id_brief | id_case | date
1 | 1 | 06/07/2010
2 | 1 | 04/07/2010
3 | 1 | 03/07/2010
4 | 2 | 18/05/2010
5 | 2 | 17/05/2010
6 | 2 | 19/05/2010
I want a result like this
breifs result
----------
id_brief | id_case | dateOrder
1 | 1 | 3
2 | 1 | 2
3 | 1 | 1
4 | 2 | 2
5 | 2 | 1
6 | 2 | 3
I think I want to do something like described here MySQL - Get row number on select, but I don't know how I would reset the variable for each id_case.
This will give you how many records are there with this id_case value and a date less than or equal to this date value.
SELECT t1.id_brief,
t1.id_case,
COUNT(t2.*) AS dateOrder
FROM yourtable AS t1
LEFT JOIN yourtable AS t2 ON t2.id_case = t1.id_case AND t2.date <= t1.date
GROUP BY t1.id_brief
Mysql is permissive about columns which can be queries using GROUP BY. With a more stric DBMS you may need GROUP BY t1.id_brief, t1.id_case.
I strongly advise you to have the right indexes on the table:
CREATE INDEX filter1 ON yourtabl (id_case, date)

Help with MySQL query to select only records with specific value in column

I have following table:
+--------+-----------+--------+
| ID | Title | Stat |
+--------+-----------+--------+
| 1 | title a | 1 |
+--------+-----------+--------+
| 1 | title b | 0 |
+--------+-----------+--------+
| 2 | title c | 1 |
+--------+-----------+--------+
| 2 | title d | 1 |
+--------+-----------+--------+
| 3 | title e | 0 |
+--------+-----------+--------+
| 3 | title f | 1 |
+--------+-----------+--------+
| 3 | title g | 1 |
+--------+-----------+--------+
I need to construct a query, where as a result only those records would be included where ALL values in column Stat meet certain condition.
For above table, how to formulate a query that would basically mean: show me records for only those ID's that have all the values in column Stat = 1 and would as a result produce following table?
+--------+-----------+--------+
| 2 | title c | 1 |
+--------+-----------+--------+
| 2 | title d | 1 |
+--------+-----------+--------+
Thanks.
Something like this?
SELECT
*
FROM table t
LEFT JOIN (
SELECT
MIN(Stat) AS Stat,
ID
FROM table
GROUP BY ID
) minstat ON t.ID = minstat.ID
WHERE minstat.Stat = 1;
Basically, the subquery computes the minimum stat per ID, whereas the outer query only selects the rows with the minimal stat equal to 1. If all rows need to satisfy a certain condition, insert a boolean expression in stead of Stat in the minimum.
Not sure if this is possible without a subquery.
This also works,
SELECT * FROM tablename t1
WHERE (
SELECT COUNT(*) FROM tablename t2
WHERE t1.ID = t2.ID AND t2.STAT = 0
) = 0
this query checks, is where a STAT with value 0 in records with same ID.
How about this:
select * from t where not (id in (select id from t where stat=0));
All 3 suggested solutions above work well, difference is only in the speed of execution. On a table where 3 records are found among approximately 7000 results are:
Martijn's: Showing rows 0 - 2 (3 total, Query took 0.0069 sec)
Alex's: Showing rows 0 - 2 (3 total, Query took 0.1162 sec)
Pavelasc's: Showing rows 0 - 2 (3 total, Query took 0.6160 sec)