MySQL Join two queries in same table - mysql

mysql> select * from fact_lab;
+---------+--------+-----+
| product | amount | box |
+---------+--------+-----+
| a | 100 | 1 |
| b | 200 | 1 |
| c | 50 | 1 |
| a | 200 | 2 |
| b | 100 | 2 |
| c | 50 | 2 |
| a | 100 | 3 |
| b | 200 | 3 |
| c | 50 | 3 |
+---------+--------+-----+
9 rows in set (0.00 sec)
I am looking for an output where I can see the total sum of amounts for each product that will show a comparison with amounts for box 2. So, the output should be like the below
+---------+--------+-----+
| product | amount | inbox2 |
+---------+--------+-----+
| a | 400 | 200 |
| b | 500 | 100 |
| c | 150 | 50 |
+---------+--------+-----+
How can i get this result in a single query?

You can get what you want with aggregation. The group by is a basic part of the SQL language. If you don't understand it, then you should study up a bit more on the language.
The second part uses condition aggregation. That is, a case statement is the argument to sum():
select fl.product, sum(amount) as amount,
sum(case when box = 2 then amount else 0 end) as inbox2
from fact_lab fl
group by fl.product;

Related

How to update a column with the number of rows that have a matching column pair?

I have a table called related_clues which lists the id's of pairs of clues which are related
| id | clue_id | related_clue_id | relatedness |
+----+---------+-----------------+-------------+
| 1 | 1 | 232 | 1 |
| 2 | 1 | 306 | 1 |
| 3 | 1 | 458 | 1 |
| 4 | 2 | 620 | 1 |
| 5 | 2 | 72 | 1 |
| 6 | 3 | 212 | 1 |
| 7 | 3 | 232 | 1 |
| 8 | 3 | 412 | 1 |
| 9 | 3 | 300 | 1 |
+----+---------+-----------------+-------------+
Eventually after a while we may reach two id's such as:
+--------+---------+-----------------+-------------+
| id | clue_id | related_clue_id | relatedness |
+--------+---------+-----------------+-------------+
| 121267 | 1636 | 38 | 1 |
| 121331 | 1636 | 38 | 1 |
+--------+---------+-----------------+-------------+
So in this case, for two distinct id values, we have the same (clue_id, related_clue_id) pair
In this case I would like the relatedness value to be updated to 2, signalling that there are two examples of this (clue_id, related_clue_id) pair. Like so:
+--------+---------+-----------------+-------------+
| id | clue_id | related_clue_id | relatedness |
+--------+---------+-----------------+-------------+
| 121267 | 1636 | 38 | 2 |
| 121331 | 1636 | 38 | 2 |
+--------+---------+-----------------+-------------+
So essentially I would like to run some SQL that sets the relatedness value to the number of times a (clue_id, related_clue_id) pair appears.
When I have no relatedness column present, and I simply run the SQL:
SELECT id, clue_id, related_clue_id, COUNT(*) AS relatedness
FROM `related_clues`
GROUP BY clue_id, related_clue_id
It gives me the required result, but of course this doesn't store the relatedness column, it simply shows the column if I run this select. So how do I permanently have this relatedness column?
You could use a update with join
Update related_clues a
INNER JOIN (
SELECT clue_id, related_clue_id, COUNT(*) AS relatedness
FROM `related_clues`
group by clue_id, related_clue_id
having count(*) = 2
) t on t.clue_id = a.clue_id
and t.related_clue_id = a.related_clue_id
set a.relatedness = t.relatedness
I would approach this as an update/join but filter out rows that don't need to be updated:
update related_clues rc join
(select clue_id, related_clue_id, COUNT(*) AS cnt
from `related_clues`
group by clue_id, related_clue_id
) t
on t.clue_id = rc.clue_id and
t.related_clue_id = rc.related_clue_id
set rc.relatedness = t.relatedness
where rc.relatedness <> t.relatedness;

Filter every column in MySQL

I have a database with three tables right now : equipements and equipements_statistics that contains the statistics of each equipements and finally stats that contains all type of statistics.
To retrieve an equipement on a filter I'm doing this query :
SELECT
*
FROM
`equipement`
INNER JOIN `equipement_stats` ON `equipement_stats`.`id_equipement` = `equipement`.`id_equipement`
INNER JOIN `stats` ON `stats`.`id_stats` = `equipement_stats`.`id_stats`
WHERE
`stats`.`id_stats` IN(1068, 1069)
GROUP BY
`equipement`.`id_equipement`
HAVING
COUNT(DISTINCT stats.id_stats) = 1
LIMIT 10
Tables are like this :
equipement
+---------------+-----------------+
| id_equipement | name_equipement |
+---------------+-----------------+
| 1 | one |
| 2 | two |
| 3 | three |
+---------------+-----------------+`
equipement_stats
+---------------+-----------+---------------+
| id_equipement | id_stats | random_number |
+---------------+-----------+---------------+
| 1 | 2 | 0 |
| 1 | 4 | 0 |
| 1 | 1069 | 1 |
| 1 | 8 | 0 |
| _____________ | _________ | _____________ |
| 2 | 1070 | 2 |
| 2 | 1069 | 3 |
| 2 | 20 | 0 |
| 2 | 40 | 0 |
+---------------+-----------+---------------+
If stats are 1068 or 1069 I must filter them on the column random_number but random_number value can be different for 1070 and 1069. How to look only for a precise id_stats with a precise random_number?
In my case for example, I would like to filter on equipements that has the stats 1070 with random_number 2 and stats 1069 with random_number 3 as the 2nd entry.
Thanks you for helping!
The easiest way to filter tuples is this:
WHERE (equipement_stats.id_stats, equipement_stats.random_number) IN ( (1068,2) , (1069,3) )

INNER JOIN shows only first row in table

I have the following data in my database:
scu_banks:
---------------------------------
| id | type | name |
|-------------------------------|
| 1 | 1 | One |
| 2 | 1 | Two |
| 3 | 2 | Three |
| 4 | 3 | Four |
---------------------------------
scu_statement:
---------------------------------
| id | code | mutation |
|-----------------------------------|
| 1 | 1 | 100 |
| 2 | 1 | 200 |
| 3 | 2 | 500 |
| 4 | 1 | 500 |
-------------------------------------
What I want to do is I want to select all the rows in table scu_banks and show the total sum of mutations. The data should be represented like:
--------------------------------------------------------------
| scu_banks.type | scu_banks.name | total | scu_banks.id |
--------------------------------------------------------------
| 1 | One | € 800.00 | 1 |
| 1 | Two | € 500.00 | 2 |
| 2 | Three | € 0.00 | 3 |
| 3 | Four | € 0.00 | 4 |
--------------------------------------------------------------
When I run my sql statement I get the following data:
---------------------------------------------------------------
| scu_banks.type | scu_banks.name | total | scu_banks.id |
--------------------------------------------------------------
| 1 | One | € 1300.00 | 1 |
---------------------------------------------------------------
The data I get in this case is not correct. € 1300.00 it the total of all the mutations in table scu_statement. The statement also dont shows the other rows in the database.
Does someone know what is wrong with my sql statement?
Here is my sql statement:
SELECT scu_banks.type,
scu_banks.name,
CONCAT('€ ', FORMAT(IFNULL(SUM(scu_statement.mutations), 0),2)) AS total,
scu_banks.id
FROM scu_banks
INNER JOIN scu_statement
ON scu_banks.id = scu_statement.code
Do the aggregation in a subquery and left join it to the banks.
SELECT b.type "scu_banks.type",
b.name "scu_banks.name",
concat('€ ', format(coalesce(x.mutation, 0), 2)) "total",
b.id "scu_banks.id"
FROM scu_banks b
LEFT JOIN (SELECT s.code,
sum(s.mutation) mutation
FROM scu_statement s
GROUP BY s.code) x
ON x.code = b.id;

Divide all columns by another column. Also divide all columns by aggregate function(min, max, sum, count, etc.)

I'm guessing this is not possible without defining a function. The idea is that you have a table like
table:
----------------
| A | B | Total|
|---|---|------|
| 1 | 2 | 3 |
| 4 | 5 | 9 |
| 6 | 7 | 13 |
----------------
select */Total from table
----------------------------
| A | B | Total |
|-------|-------|----------|
| 0.333 | 0.667 | 1.00 |
| 0.8 | 0.556 | 1.00 |
| 0.462 | 0.538 | 1.00 |
----------------------------
select */(select max(*) from table) from table
----------------------------
| A | B | Total |
|-------|-------|----------|
| 0.167 | 0.286 | 0.231 |
| 0.667 | 0.714 | 0.692 |
| 1.000 | 1.000 | 1.000 |
----------------------------
So you want operators on your output. You can simply do this to get your first example:
SELECT A/total, B/total, (A+B)/total FROM `table`
You don't even need a 'total' column:
SELECT A/(A+B), B/(A+B), 1 as total FROM `table`
Second one, if you are trying to get the average, same logic applies.

Finding average of the column generated from sql query having group by function

I want to find the average of the following data via mysql query (assume these are 719 rows).
| 1 |
| 3 |
| 1 |
| 2 |
| 2 |
| 1 |
| 1 |
| 2 |
| 1 |
| 1 |
| 2 |
| 1 |
| 2 |
| 1 |
| 2 |
| 1 |
| 1 |
+----------+
719 rows in set (2.43 sec)
SELECT COUNT(*) FROM osdial_agent_log WHERE DATE(event_time)='2015-11-01' GROUP BY lead_id;
I ran this query to get that data
Can someone help me to find the average for the above data.
Use
SELECT AVG(total)
FROM (SELECT COUNT(*) AS total
FROM osdial_agent_log
WHERE DATE(event_time)='2015-11-01'
GROUP BY lead_id) t