I have a table like:
Number | Event | Weight
1 4 150
1 4 160
2 5 200
2 4 200
3 6 190
3 6 195
For each row, I would like to subtract from its Weight, the Weight of another row where Number and Event matches (if exists). The desired output is:
Number | Event | Weight | DIFF
1 4 150 -10
1 4 160 10
2 5 200 NULL
2 4 200 NULL
3 6 190 -5
3 6 195 5
Is such an operation possible? Not sure if relevant, eventually I would need to turn this query into a view. Thanks in advance.
You need a left join:
select
t.*,
t.weight - tt.weight diff
from tablename t left join tablename tt
on tt.number = t.number and tt.event = t.event and tt.weight <> t.weight
It can be done by simply substracting the column in the joined table. When one of the operands is null, the result of the arithmetic operation is null:
select a.Number, a.Event, a.Weight, a.Weight - b.Weight as DIFF
from a
left join b on a.Number = b.Number and a.Event = b.Event
Related
What is the best way to subtract the lowest value from all values by group?
Something like:
ID Name Value
1 A 10
1 B 40
1 C 100
2 A 20
2 B 80
2 C 90
3 A 4
3 B 7
3 C 8
turn to:
ID Name Value
1 A 0
1 B 30
1 C 90
2 A 0
2 B 60
2 C 70
3 A 0
3 B 3
3 C 4
Use window functions:
select id, name, value - min(value) over (partition by id) as
from t;
If you actually want to update the values, in MySQL, aggregation and join are probably the simplest solution:
update t join
(select id, min(value) as min_value
from t
group by id
) tt
on t.id = tt.id
set value = value - min_value
where min_value <> 0;
I have a list of values in my database.
k v
1 5000
1 100
1 120
1 3
2 5000
2 100
2 120
2 4
3 10000
3 120
3 100
3 4
4 10
4 120
4 110
4 5000
I want to calculate the average of each k but I need to ignore the highest and lowest value of v for each k. (to remove spikes)
select avg(v) from table where v > min(v) and v < max(v) group by k
results in an :
"Invalid use of group function"
I was thinking that this is a quite common task but I wasn't able to find any ideas from the docs.
Thanks for any advise.
One way to do this without worrying about whether there are duplicate min and max values of v (assuming you only want to ignore one of each) is to take the average as SUM(v)/COUNT(v), but subtracting the min and max values from the computation:
SELECT k, (SUM(v) - MAX(v) - MIN(v)) / (COUNT(v) - 2) AS average
FROM data
GROUP BY k
Output:
k average
1 110
2 110
3 110
4 115
Demo on dbfiddle
select avg(v) , k
from table
group by k
having k <> min (v) and k<> max (v)
First get the min and max v for each k and then left join the table to the results so to get the average of the non matching rows:
select
t.k, avg(t.v) average
from tablename t left join (
select k, min(v) minv, max(v) maxv
from tablename
group by k
) g on g.k = t.k and t.v in (g.minv, g.maxv)
where g.k is null
group by t.k
See the demo.
Results:
| k | average |
| --- | ------- |
| 1 | 110 |
| 2 | 110 |
| 3 | 110 |
| 4 | 115 |
Link: Demo
select t1.k, avg(t1.v) average
from numbers t1 left join (
select k, min(v) minv, max(v) maxv
from numbers
group by k
) t2 on t2.k = t1.k and t1.v in (t2.minv, t2.maxv)
where t2.k is null
group by t1.k
I have 2 table on my transaction
Table One
id | date | cust_id | driver_number
1 2019-01-02 1 F 3350 NN
2 2019-04-02 2 AX 111 Z
3 2019-05-02 3 S 787 X
4 2019-05-02 4 T 9090 M
5 2019-06-02 3 P 8989 L
Table Two
driver_number | price
F 3350 NN 350000
AX 111 Z 400000
S 787 X 375000
T 9090 M 900000
P 8989 L 500000
How do I count total transaction from two tables above in one month as per requested .
In example, request for total transaction in May so the result is like below
period | total
May 1275000
Thank you
Using MONTH(T1.date) = 5 and SUM(price) the expected result is achievable
SELECT MONTH(T1.date) AS Period, SUM(price) AS `Total`
FROM TableOne T1
JOIN TableTwo T2 ON T2.driver_number = T1.driver_number
WHERE MONTH(T1.date) = 5
GROUP BY MONTH(T1.date)
I have tables like these:
A table B table
-------------------- -----------------------------------
item_ID | item_Name item_ID | option_ID | option_Value
-------------------- -----------------------------------
1 item_a 2 34 2000
2 item_b 2 45 3400
3 item_c 2 12 1200
4 item_d 3 34 500
5 item_e 3 13 500
6 item_f 4 45 700
I wrote a query to get items, for example which have option 34 = 2000 and option 12 = 1200 is:
SELECT A.item_ID, A.item_name
FROM A
LEFT JOIN B ON A.item_ID = B.item_ID
WHERE B.option_ID IN (34, 1200) AND
B.option_Value IN (1200, 2000) AND
GROUP BY A.item_ID
HAVING COUNT(A.item_ID) >= 2 /* count of option used for search, can be more*/
My problem is for some options I want to get range result , for example: where option id 34 is between 1000 and 2000 and option 12 is lower than 4000
Note : (option_id, option_value) pair is unique and i want to get items that match all of the conditions
How about this?
SELECT A.item_ID, A.item_name
FROM A
LEFT JOIN B ON A.item_ID = B.item_ID
WHERE (B.option_ID=34 AND B.option_value BETWEEN 1000 AND 2000)
OR (B.option_ID=12 AND B.option_value BETWEEN 0 AND 4000)
GROUP BY A.item_ID
HAVING COUNT(A.item_ID) >= 2
Maybe I didn't understand the question completely?
This should give you what you want:
WHERE
B.option_ID = 34 AND B.option_Value BETWEEN 1000 AND 2000
OR
B.option_ID = 12 AND B.option_Value < 4000
There might be a better way to do this if there was some rule according to which you want to filter... Otherwise, just use OR and AND to achieve what you want.
I have seen variations of this question asked but either they didn't apply or I didn't understand the answer/s.
I have two tables one table with charges types with additional cost and one of charges. I want to join them to get the appropriate values. I want to join the tables where the charge is between the startDate and the endDate and on the types. If there is not a match I want it to choose the type -1 (same condition for dates). If there is not a match I don't want it to show up in the results.
I initially was was going to do a normal left join ordered by 'type' desc and then group by 'type' believing that it would only leave me with the first type but I read that MySQL advises against this because the group by can be unpredictable and not always return the first match.
Tables:
startDate | endDate | type | addCost
--------------------------------------
2010-01-01 2010-12-31 1 100
2010-01-01 2010-12-31 2 200
2010-01-01 2010-12-31 -1 50
2011-01-01 2012-02-20 3 350
2011-01-01 2012-02-20 1 150
2011-01-01 2012-02-20 -1 75
chargeDate | type | cost
---------------------------
2010-10-01 1 10
2010-11-01 2 20
2010-12-01 4 40
2011-02-01 3 60
2011-03-01 2 25
2011-04-01 4 25
Desired Results:
chargeDate | type | cost | addCost
---------------------------------
2010-10-01 1 10 100
2010-11-01 2 20 200
2010-12-01 4 40 50
2011-02-01 3 60 350
2011-03-01 2 25 75
I'm using a subquery where I am trying to join charges with charges_types. If the join doesn't succeed, type is null and with coalesce I set type_c as -1, otherwise I set it to type. Then I join this subquery with charges_types again, and on the join clause i use type_c instead of type:
select c.chargeDate, c.type, c.cost, ct.addCost
from
(select
charges.chargeDate,
charges.type,
coalesce(charges_types.type, -1) as type_c,
charges.cost
from
charges left join charges_types
on charges.chargeDate between charges_types.startDate and charges_types.endDate
and charges.type = charges_types.type) c
inner join charges_types ct
on c.chargeDate between ct.startDate and ct.endDate
and c.type_c = ct.type