Conditional output in MYSQL groupb function - mysql

So I have a table in this form
+----+-----+
| id | Val |
+----+-----+
| 1 | 20 |
| 1 | 30 |
| 2 | 0 |
| 2 | 80 |
| 3 | 45 |
| 3 | 60 |
| 4 | 0 |
| 4 | 30 |
+----+-----+
I want to do a groupby on the id and the sum the values in the Val column. Only, if one of the values is zero, the resultant sum should also be zero
For the above table, the output would be
+----+-------+
| id |SumVal |
+----+-------+
| 1 | 50 |
| 2 | 0 |
| 3 | 105 |
| 4 | 0 |
+----+-------+
I've tried using conditional statements(CASE and IF) inside the sum function but those conditions seem to work only on the individual elements.
Any pointers ?

Using SUM and IF:
SELECT id, (SUM(val) * IF(val = 0, 0, 1)) AS SumVal FROM idval GROUP BY id;

Check This Simple Query.
select id ,SUM(val)
from #Table
where val=0
group by ID
union
select id ,SUM(val)
from #Table
where id not in (select id from #Table where val=0)
group by ID
OutPut :

try this
select id,if(cast(val as signed),sum(val),0) as total from tbl_name group by id;

Related

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)

about mysql excute order by 1 and rand(1)?

In mysql I built a table, which id is int type, name and password is varchar type.
excute
select * from test.new_table order by rand(1);
then the result is:
This is because after set seed for rand the sequence is fixed, I already know.But if excute
select * from test.new_table order by 1 and rand(1);
then the result is:
For such a result I do not understand. In addition, if excute order by 'xxx' the results are arranged.
Not quite understand, hope you to give pointers.
You can view the results of the expression as part of your query:
mysql> select *, 1, rand(1), 1 and rand(1) from new_table order by 1 and rand(1);
+----+------+----------+---+---------------------+---------------+
| id | name | password | 1 | rand(1) | 1 and rand(1) |
+----+------+----------+---+---------------------+---------------+
| 1 | ghi | 111 | 1 | 0.40540353712197724 | 1 |
| 3 | abc | 234 | 1 | 0.1418603212962489 | 1 |
| 5 | 5 | 5 | 1 | 0.04671454713373868 | 1 |
| 7 | 7 | 7 | 1 | 0.6108337804776 | 1 |
| 2 | jkl | 123 | 1 | 0.8716141803857071 | 1 |
| 4 | def | 555 | 1 | 0.09445909605776807 | 1 |
| 6 | 6 | 6 | 1 | 0.9501954782290342 | 1 |
+----+------+----------+---+---------------------+---------------+
See how the boolean expression always results in 1?
As #Barmar described, any expression 1 and n results in either 0 or 1, depending on the value of n being zero or nonzero.
So your expression ORDER BY 1 AND RAND(1) is just like ORDER BY true (a constant expression) which means the ordering is a tie between every row, and MySQL orders them in an arbitrary way.
But arbitrary is not the same as random.

Select the first rows of a table (that has a column with int values which sum of values is less than the input

My input is 5 in this case, and I want to select the first two rows, to delete the first row and to update the second one, putting the value 7 instead of 10.
I tried to do this query but it's not enough:
SELECT SUM(`Qty in acquisto`) AS total,`Prezzo in acquisto`
FROM `book`
GROUP BY `Qty in acquisto`
HAVING COUNT(*) >5
You could use variables to get the rows of interest, together with the information you need to update the records:
SELECT *
FROM (
SELECT `Qty in acquisto`,
`Prezzo in acquisto`,
#take := least(`Qty in acquisto`, #needed) as taken,
`Qty in acquisto` - #take as adjusted_acquisto,
#needed := #needed - #take as still_needed
FROM book,
(select #needed := 5) as init
ORDER BY `Prezzo in acquisto` DESC) base
WHERE taken + still_needed > 0
The output for the sample data is:
| Qty in acquisto | Prezzo in acquisto | taken | adjusted_acquisto | still_needed |
|-----------------|--------------------|-------|-------------------|--------------|
| 2 | 1000 | 2 | 0 | 3 |
| 10 | 960 | 3 | 7 | 0 |
See SQL fiddle
In the innermost query, with alias init, you pass the number of books you need (5 in the example).
So in column adjusted_acquisto you find the value you need to perform the deletes and update:
If that value is 0, delete the corresponding record.
It that value is not 0, update the Qty with that value.
E.g.:
SELECT * FROM my_table;
+------+--------+
| id | amount |
+------+--------+
| 800 | 8 |
| 900 | 3 |
| 950 | 4 |
| 960 | 10 |
| 1000 | 2 |
+------+--------+
SELECT n.id
, GREATEST(amount-#x,0) new_amount
, #x:=GREATEST(#x-amount,0) x
FROM my_table n
, (SELECT #x:=5) vars
ORDER
BY id DESC;
+------+--------+------------+------+
| id | amount | new_amount | x |
+------+--------+------------+------+
| 1000 | 2 | 0 | 3 |
| 960 | 10 | 7 | 0 |
| 950 | 4 | 4 | 0 |
| 900 | 3 | 3 | 0 |
| 800 | 8 | 8 | 0 |
+------+--------+------------+------+

INSERT and SELECT sequence in MySQL

If I insert a value with an order by name like this.
+------------------+
| Table: example |
+------------------+
| Name | Value |
+---------+--------+
| A | 153 |
| B | 10 |
| C | 20 |
| D | 50 |
| E | 100 |
+---------+--------+
When I select the value with a query
select * from example
or
select * from example limit 2
without a where, order by or group by, is the order of the result defaulted to the insert order??
Thanks,

MySQL sum per IDs without subqueries

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