MySQL sum per IDs without subqueries - mysql

I'm working on a huge dataset, with a table that looks like this :
+----+---------+--------+--------+
| id | otherid | value1 | value2 |
+----+---------+--------+--------+
| 1 | 1 | 2 | 5 |
| 1 | 1 | 4 | 8 |
| 1 | 2 | 3 | 6 |
| 2 | 123 | 1 | 4 |
+----+---------+--------+--------+
I need to multiply value1 and value2 for each row, and sum values per id and otherid. A result table might be:
+----+---------+-----+
| id | otherid | sum |
+----+---------+-----+
| 1 | 1 | 42 | ((2*5)+(4*8))
| 1 | 2 | 18 | (3*6)
| 2 | 123 | 4 | (1*4)
+----+---------+-----+
My question is if it is possible to avoid subqueries to do this, I only found solutions that used them.
Thanks!

it's easy.
SELECT id,
otherid,
SUM(value1*value2) AS sum
FROM your_table
GROUP BY id, otherid;

Try Below Query
SELECT ID,otherid ,SUM(value1 * value2) sum
FROM TABLE1
GROUP BY ID,otherid

Related

How to select the most spanning ranges

My table looks like
+----+------+----+
| Id | from | to |
+----+------+----+
| 1 | 1 | 10 |
| 1 | 10 | 12 |
| 1 | 12 | 23 |
| 1 | 24 | 26 |
| 2 | 2 | 8 |
| 2 | 3 | 4 |
| 2 | 4 | 10 |
+----+------+----+
Now I want to group by Id and select the most spanning range.
So the result table should look like this:
+----+-------------+
| Id | range |
+----+-------------+
| 1 | 1-23, 24-26 |
| 2 | 2-10 |
+----+-------------+
I do not even know how to start.
Thanks in advance for the help!
You can achieve something similar to this by writing a MySQL select query with the CONCAT() function. You can use GROUP BY to categorize the data. But keep in mind that from,to and range are reserved words in MySQL. Therefore, I'll use fooFrom, fooRange and fooTo as column name for this example
Example:
SELECT Id, CONCAT(fooFrom, "-", fooTo) AS "fooRange" FROM fooTable GROUP BY id;
This example code will output:
id | fooRange
1 | 5-6
2 | 12-88
But I'm not sure about how to concat all the content into a one-column value.

Update MySQL table with smallest value from another table

I have been looking around quite a lot but I can't seem to find a solution to this problem.
I got two tables:
|---------------------|-------------------|
| ID | Value |
|---------------------|-------------------|
| 1 | NULL |
| 2 | NULL |
| 3 | NULL |
| 4 | NULL |
|---------------------|-------------------|
...
|---------------------|-------------------|
| ID | Value |
|---------------------|-------------------|
| 1 | 7 |
| 1 | 18 |
| 2 | 21 |
| 2 | 2 |
| 4 | 103 |
|---------------------|-------------------|
...
Basically what I wanna do is update the NULL-fields from the first table with the smallest value from the second table where there are matching IDs.
So that in the end it looks something like this:
|---------------------|-------------------|
| ID | Value |
|---------------------|-------------------|
| 1 | 7 |
| 2 | 2 |
| 3 | NULL |
| 4 | 103 |
|---------------------|-------------------|
...
I tired out a bunch of things but failed. Can anyone help me?
You could use a sub query:
update t1
inner join (select ID, min(Value) as minimum from t2 group by ID) tempt2 on t1.ID=tempt2.ID
set t1.value=tempt2.minimum;
Basically, you're looking up that minimum value in the second table for each ID, you call that table tempt2, and you join on that.

MySQL nested Select statement with subquery

I am struggeling with a database query for 2 Hours now.
There is the following database structure:
article table
+---------------+-------------+
| id | ordernumber |
+---------------+-------------+
| 1 | 3243 |
| 2 | 3344 |
| 3 | 3423 |
| 4 | 7687 |
+---------------+-------------+
variant table
+----+-----------+-------+-------+
| id | articleId | stock | price |
+----+-----------+-------+-------+
| 1 | 1 | 3 | 10,99 |
| 2 | 1 | 0 | 10,99 |
| 3 | 1 | 1 | 10,99 |
| 4 | 2 | 0 | 11,99 |
| 5 | 2 | 0 | 11,99 |
| 6 | 2 | 1 | 11,99 |
+----+-----------+-------+-------+
I want to get all Articles where all but one variant have 0 stock.
Is this even possible with a plain sql statement? I tried with a subquery, but without success, since the subquery gets executed first and I would need to pass values from the current record of the resultset of the outer query.
Any help is much appreciated.
Edit:
Expected Result:
+----+-------------+
| id | ordernumber |
+----+-------------+
| 2 | 3344 |
+----+-------------+
If you want the full information for the variant:
select v.*
from variants v
where v.stock > 0 and
not exists (select 1
from variants v2
where v2.articleID = v.articleID and
v2.stock > 0 and
v2.id <> v.id
);
Note: this assumes that the duplicated "5" is a typo and that the ids really are unique in the table.
This can be done using group by and having.
select articleID
from variants
group by articleID
having count(*) - 1 = count(case when stock = 0 then 1 end)

mysql: order -> limit -> sum... possible?

i am loosing it over the following problem:
i have a table with participants and points. each participant can have up to 11 point entries of which i only want the sum of the top 6.
in this example lets say we want the top 2 of 3
+----+---------------+--------+
| id | participantid | points |
+----+---------------+--------+
| 1 | 1 | 11 |
+----+---------------+--------+
| 2 | 3 | 1 |
+----+---------------+--------+
| 3 | 3 | 4 |
+----+---------------+--------+
| 4 | 2 | 3 |
+----+---------------+--------+
| 5 | 1 | 5 |
+----+---------------+--------+
| 6 | 2 | 10 |
+----+---------------+--------+
| 7 | 2 | 9 |
+----+---------------+--------+
| 8 | 1 | 3 |
+----+---------------+--------+
| 9 | 3 | 4 |
+----+---------------+--------+
as a result i want something like
+---------------+--------+
| participantid | points |
+---------------+--------+
| 2 | 19 |
+---------------+--------+
| 1 | 16 |
+---------------+--------+
| 3 | 8 |
+---------------+--------+
(it should be ordered DESC by the resulting points)
is this at all possible with mysql? in one query?
oh and the resulting participant ids should be resolved into the real names from another 'partcipant' table where
+----+------+
| id | name |
+----+------+
| 1 | what |
+----+------+
| 2 | ev |
+----+------+
| 3 | er |
+----+------+
but that should be doable with a join at some point... i know...
Using one of the answers from ROW_NUMBER() in MySQL for row counts, and then modifying to get the top.
SELECT ParticipantId, SUM(Points)
FROM
(
SELECT a.participantid, a.points, a.id, count(*) as row_number
FROM scores a
JOIN scores b ON a.participantid = b.participantid AND cast(concat(a.points,'.', a.id) as decimal) <= cast(concat(b.points,'.', b.id) as decimal)
GROUP BY a.participantid, a.points, a.id
) C
WHERE row_number IN (1,2)
GROUP BY ParticipantId
Had an issue with ties until I arbitrarily broke them with the id

MySQL counting total number of zeros

I have a table that looks like
| id | day1 | day2 | day3 | day4 | day5 |
| 1 | 4 | 0 | 5 | 0 | 0 |
| 2 | 2 | 0 | 0 | 4 | 1 |
and I want to find to total number of zero entries for each id to give
| id | total_zeros |
| 1 | 3 |
| 2 | 2 |
SELECT id, (day1=0)+(day2=0)+(day3=0)+(day4=0)+(day5=0) total_zeroes
FROM table
Try this one:
select
id, if(day1=0,1,0)+if(day2=0,1,0)+ if(day3=0,1,0)+if(day4=0,1,0)+if(day5=0,1,0) as total
from test
DEMO HERE
Why do people insist on making such un-usable tables?
You will have to use a case statement, and evaluate each column individually, and then add up the results.