I have a simple table with 10000 rows
product_id | price | price_inc_vat | vat_rate
I want to be able to update the value of price_inc_vat based on the value of price
I have tried this
UPDATE 1_products AS s3,
1_products AS t3
SET t3.price_inc = ROUND(s3.price*1.3,2)
WHERE s3.vat_rate = 20 AND t3.vat_rate=20;
It doesn't error but seems to be taking a very long time as I had to kill the query after 1/2 hour.
Why the join?
UPDATE products SET price_inc_vat = ROUND(price*1.3,2) WHERE vat_rate=20;
UPDATED
I'm not quite sure what you are trying to achieve by updating a product's "Inc. price" with another products price, but the reason that your query is taking so long is because of the way that you are joining.
mysql> create table t1 (product_id integer unsigned primary key, price decimal(10,2), price_inc_vat decimal(10,2), vat_rate integer unsigned);
mysql> insert into t1 values (1, 1.00, 1.20, 20), (2, 2.00, 2.40, 20), (3, 1.00, 1.30, 30);
mysql> select * from (t1 as s3, t1 as t3) where s3.vat_rate=20 and t3.vat_rate=20;
1 1.00 1.20 20 1 1.00 1.20 20
2 2.00 2.40 20 1 1.00 1.20 20
1 1.00 1.20 20 2 2.00 2.40 20
2 2.00 2.40 20 2 2.00 2.40 20
mysql> select s3.*, t3.*, round(s3.price * 1.3, 2) from (t1 as s3, t1 as t3) where s3.vat_rate=20 and t3.vat_rate=20;
1 1.00 1.20 20 1 1.00 1.20 20 1.30
2 2.00 2.40 20 1 1.00 1.20 20 2.60
1 1.00 1.20 20 2 2.00 2.40 20 1.30
2 2.00 2.40 20 2 2.00 2.40 20 2.60
mysql> update (t1 as s3, t1 as t3) set t3.price_inc_vat=round(s3.price*1.3, 2) where s3.vat_rate=20 and t3.vat_rate=20;
mysql> select * from (t1 as s3, t1 as t3) where s3.vat_rate=20 and t3.vat_rate=20;
1 1.00 1.30 20 1 1.00 1.30 20
2 2.00 1.30 20 1 1.00 1.30 20
1 1.00 1.30 20 2 2.00 1.30 20
2 2.00 1.30 20 2 2.00 1.30 20
If you are trying to set product prices based upon a previous price set then perhaps the following will help clarify things:
mysql> create table t1 (
product_id integer unsigned,
vat_rate integer unsigned,
price decimal(10,2),
price_inc_vat decimal(10,2),
primary key(product_id, vat_rate)
);
mysql> insert into t1 (product_id, price, price_inc_vat, vat_rate) values (1, 1.00, 1.20, 20), (2, 2.00, 2.40, 20), (1, 1.00, 0, 30), (2, 2.00, 0, 30);
mysql> create temporary table tmp1 like t1;
mysql> insert into tmp1 select * from t1;
mysql> select * from t1;
1 20 1.00 1.20
1 30 1.00 0.00
2 20 2.00 2.40
2 30 2.00 0.00
mysql> select * from tmp1;
1 20 1.00 1.20
1 30 1.00 0.00
2 20 2.00 2.40
2 30 2.00 0.00
mysql> update t1 left join tmp1 on t1.product_id=tmp1.product_id and t1.vat_rate > tmp1.vat_rate set t1.price_inc_vat = round(tmp1.price*(1+t1.vat_rate/100), 2) where tmp1.vat_rate = 20;
mysql> select * from t1;
1 20 1.00 1.20
1 30 1.00 1.30
2 20 2.00 2.40
2 30 2.00 2.60
So you have a field for price and another for price_inc_vat and yet another for vat_rate? Why not just store price and vat_rate and calculate price_inc_vat when it's needed?
Also, why are you multiplying by 1.3 when the VAT you're targeting appears to be 20%?
All these logical inconsistencies aside, couldn't you just do the following?
UPDATE products
SET price_inc_vat = ROUND(price * 1.3, 2)
WHERE vat_rate = 20
Or to update everything after a VAT change, disregarding the 10% markup:
UPDATE products
SET price_inc_vat = ROUND(price * (1+vat_rate/100), 2)
Related
ub_referrerid ub_redeemerid ub_referrer_cashbonus ub_redeemer_cashbonus
186 190 100 60
154 186 100 60
190 201 100 60
154 189 100 60
190 211 100 60
154 255 100 60
190 297 100 60
Now I have To Find The Sum Of cash Bonus on the basis of userid
suppose I have userid 154 which is present in both ub_referrerid and ub_redeemerid now I have to find the sum of userid 154 from column ub_referrer_cashbonus and ub_redeemer_cashbonus using MySQL
We create a CTE with UNION ALL two queries : one for referers bonuses and one for referees bonuses.
We then amalgamate the results.
create table ub(
ub_referrerid int,
ub_redeemerid int,
ub_referrer_cashbonus int,
ub_redeemer_cashbonus int);
insert into ub values
(186 ,190 ,100, 60 ),
(154 ,186, 100 ,60 ),
(190 ,201 ,100, 60 ),
(154 ,189 ,100, 60),
( 190 ,211, 100, 60 ),
(154 ,255 ,100 ,60),
( 190 ,297 ,100, 60);
with bonus as (
select
ub_referrerid id ,
sum(ub_referrer_cashbonus) referBonus,
0 redbonus
from
ub
group by
ub_referrerid
union all
select
ub_redeemerid id,
0 refCash,
sum(ub_redeemer_cashbonus) redCash
from
ub
group by
ub_redeemerid
)
select
b.id ,
sum(b.referbonus) refBonus,
sum(b.redBonus) redbonus,
sum(b.referBonus)+sum(redBonus) total
from bonus b
group by id
order by id ;
id | refBonus | redbonus | total
--: | -------: | -------: | ----:
154 | 300 | 0 | 300
186 | 100 | 60 | 160
189 | 0 | 60 | 60
190 | 300 | 60 | 360
201 | 0 | 60 | 60
211 | 0 | 60 | 60
255 | 0 | 60 | 60
297 | 0 | 60 | 60
db<>fiddle here
You have to use GROUP BY clause based on ub_referrerid and ub_redeemerid with same alias userid. Then use UNION ALL (In this operation, column names with alias must be same).
SELECT userid,SUM(bonus) AS bonus
FROM
(
SELECT ub_referrerid as userid,
(ub_referrer_cashbonus+ub_redeemer_cashbonus) as bonus
FROM YOUR_TABLE_NAME
UNION ALL
SELECT ub_redeemerid as userid,
(ub_referrer_cashbonus+ub_redeemer_cashbonus) as bonus
FROM YOUR_TABLE_NAME
) CASH
GROUP BY userid
ORDER BY userid;
table_a
user_id canon_id ratio (count of 1 / total)
1 1000 0.33
2 1000 0.33
3 1000 0.33
11 4344 0.50
88 4344 0.50
7 2023 0
8 2023 0
10 2023 0
12 3333 0.80
17 3333 0.80
18 3333 0.80
19 3333 0.80
20 3333 0.80
table_b
user_id flag
1 0
2 0
3 1
11 1
88 0
14 0
7 1
8 1
10 1
12 1
17 1
18 1
19 1
20 0
In the above case, how can I join tables and populate the table_a.ratio by using flags from another MySQL table? the formula for ratio is (count of 1 / total user_ids associated with that canon_id)
If you are running MySQL 8.0, you can use window functions. avg() comes to mind:
select a.*, avg(b.flag) over(partition by a.canon_id) ratio
from table_a a
left join table_b b on b.user_id = a.user_id
In earlier versions, a correlated subquery might be an acceptable solution:
select
a.*,
(
select avg(b1.flag)
from table_a a1
left join table_b b1 on b1.user_id = b.user_id
where a1.canon_id = a.canon_id
) ratio
from table_a a
I found tons of examples in Stackoverflow about how to select first and last row in a group but I cannot adapt them to my need. Alas my limited knowledge of MySQL doesn't help.
Some data (date_time, val1 and val2) are saved in random moments. I need to group them for 15 minutes and then calculate, for each 15 min interval:
number of row in the interval (done)
val1 min (done)
val1 avg (done)
val1 max (done)
first val2 in the group (done, easy with COALESCE)
last val2 in the group (here I need your help)
Here's my data, desired result, and best effort to date...
# what I would like to obtain:
#_timeslice _count _min_val1 _avg_val1 _max_val1 _first_val2 _last_val2
# 2017-11-01T00:00:00Z 4 90 100 110 200 210
# 2017-11-01T00:15:00Z 3 100 110 120 240 230
# 2017-11-01T00:30:00Z 2 110 120 130 270 265
# 2017-11-01T00:45:00Z 4 80 112.5 150 290 320
CREATE TABLE `test-table`
(`date_time` datetime, `val1` float, `val2` float);
INSERT INTO `test-table`
(`date_time`, `val1`, `val2`)
VALUES
('2017-11-01 00:00:00', 100, 200), # first 15 min
('2017-11-01 00:01:00', 110, 190),
('2017-11-01 00:02:05', 90, 220),
('2017-11-01 00:14:00', 100, 210),
('2017-11-01 00:15:00', 100, 240), # second 15 min
('2017-11-01 00:16:00', 110, 250),
('2017-11-01 00:28:00', 120, 230),
('2017-11-01 00:30:00', 110, 270), # third 15 min
('2017-11-01 00:44:59', 130, 265),
('2017-11-01 00:50:00', 120, 290), # fourth 15 min
('2017-11-01 00:55:00', 150, 300),
('2017-11-01 00:57:00', 100, 280),
('2017-11-01 00:58:00', 80, 320)
;
SELECT FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(`date_time`)/900)*900) AS _timeslice,
COUNT(*) AS _count,
min(`val1`) as _min_val1,
avg(`val1`) as _avg_val1,
max(`val1`) as _max_val1,
coalesce(`val2`) as _first_val2 # returns the first val2 in the group
# ----> how to add here the last val2 for the group?
FROM `test-table`
GROUP BY _timeslice;
...and here's a fiddle of same SQLFiddle_grouping_15_min
Can somebody help me with the syntax to use?
SELECT a.*
FROM `test-table` a
JOIN
( SELECT FLOOR(UNIX_TIMESTAMP(date_time)/900) timeslice
, MIN(date_time) min_date_time
, MAX(date_time) max_date_time
FROM `test-table`
GROUP
BY timeslice
) b
ON b.timeslice = FLOOR(UNIX_TIMESTAMP(a.date_time)/900)
AND a.date_time IN(b.min_date_time,b.max_date_time);
+---------------------+------+------+
| date_time | val1 | val2 |
+---------------------+------+------+
| 2017-11-01 00:00:00 | 100 | 200 |
| 2017-11-01 00:14:00 | 100 | 210 |
| 2017-11-01 00:15:00 | 100 | 240 |
| 2017-11-01 00:28:00 | 120 | 230 |
| 2017-11-01 00:30:00 | 110 | 270 |
| 2017-11-01 00:44:59 | 130 | 265 |
| 2017-11-01 00:50:00 | 120 | 290 |
| 2017-11-01 00:58:00 | 80 | 320 |
+---------------------+------+------+
I found a simple solution with a straightforward syntax. It is possibly the easiest for a newbie like me:
SELECT FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(`date_time`)/900)*900) AS _timeslice,
COUNT(*) AS _count,
min(`val1`) as _min_val1,
avg(`val1`) as _avg_val1,
max(`val1`) as _max_val1,
SUBSTRING_INDEX(GROUP_CONCAT(CAST(`val2` AS CHAR) ORDER BY date_time), ',', 1) AS _first_val2,
SUBSTRING_INDEX(GROUP_CONCAT(CAST(`val2` AS CHAR) ORDER BY date_time DESC), ',', 1) AS _last_val2
FROM `test-table`
GROUP BY _timeslice;
Fiddle at SQLFiddle_solved
I am trying to create a query from sales-order-details and invoice for an income statement sales revenues.
when I put this into the sql to look up the query
SELECT salesno, quantity, price, price* quantity
FROM inventory, sales_order_details
LIMIT 0, 5
it keeps giving the same quantity and sales number for all of them. the prices are right and so is the price.. what am I doing wrong?
salesno quantity price and quantity*price
5455 153 2.00 306.00
5455 153 6.00 918.00
5455 153 5.00 765.00
5455 153 4.00 612.00
5455 153 5.00 765.00
My sales-order-details table looks like this
SQL query:
SELECT * FROM `sales_order_details` ORDER BY `sales_order_details`.`quantity` DESC LIMIT 0, 5 ;
Rows: 5
salesno inno quantity
5459 6319 290
5458 6318 220
5455 6315 153
5457 6317 110
5456 6316 101
and my invoice table looks like this
SQL query:
SELECT * FROM `inventory` LIMIT 0, 30 ;
Rows: 5
inno pname qoh price cost
6315 roses 500 2.00 1.00
6316 sunflowers 200 6.00
6317 dandy lions 270 5.00
6318 violets 300 4.00 2.00
6319 tulips 130 5.00 2.50
I need inno, pname, price, quantity and the price*quantity
(Please refer to SQLFiddle for a working example of this post)
I have a table with stock information, as follows:
sp100_id _date bullishness agreement
----------------------------------------------
1 2011-03-16 1.01 0.33
1 2011-03-17 0.85 1.28
1 2011-03-18 0.89 1.25
1 2011-03-21 1.46 1.21
1 2011-03-22 0.39 2.53
2 2011-03-16 3.07 1.27
2 2011-03-17 2.09 0.80
2 2011-03-18 0.91 0.12
2 2011-03-21 1.50 0.00
2 2011-03-22 2.62 1.10
3 2011-03-16 0.73 1.13
3 2011-03-17 1.13 1.21
3 2011-03-18 1.12 0.45
3 2011-03-21 1.00 1.01
3 2011-03-22 1.00 0.53
4 2011-03-16 0.40 1.10
4 2011-03-17 2.40 0.03
4 2011-03-18 3.16 0.10
4 2011-03-21 0.86 0.50
4 2011-03-22 1.00 0.10
I need to order the companies (sp100_id) by their averge bullishness over time into a top-3:
SELECT
sp100_id,
AVG(bullishness) as bullishness,
AVG(agreement) AS agreement
FROM stocks
WHERE _date BETWEEN '2011-03-16' AND '2011-03-22'
GROUP BY sp100_id LIMIT 3
This works fine, as the result is
SP100_ID BULLISHNESS AGREEMENT
2 2.038 0.658
4 1.564 0.366
3 0.996 0.866
Now that I have the top-3, I need the top-3 to be re-ordered by AGREEMENT, ascending:
SP100_ID BULLISHNESS AGREEMENT
4 1.564 0.366
2 2.038 0.658
3 0.996 0.866
Is this possible to do with one query? I tried the following but it didn't work. It still only orders by bullishness
SELECT
sp100_id,
AVG(bullishness) as bullishness,
AVG(agreement) AS agreement
FROM stocks
WHERE _date BETWEEN '2011-03-16' AND '2011-03-22'
GROUP BY sp100_id
ORDER BY bullishness DESC, agreement ASC LIMIT 3
So to be clear: (1) I need to find the top-3 companies with highest average bullsihness (2) this top-3 then needs to be ordered from lowest to highest agreement. Preferably with one query. Do you know how?
It's called structured query language because you can build structures in which queries (aka virtual tables) are nested inside other queries.
Take your first query, which is correct except it needs its own ORDER BY clause, and nest it in another, like so.
SELECT *
FROM (
SELECT sp100_id,
AVG(bullishness) as bullishness,
AVG(agreement) AS agreement
FROM stocks
WHERE _date BETWEEN '2011-03-16' AND '2011-03-22'
GROUP BY sp100_id
ORDER BY bullishness DESC
LIMIT 3
) subquery
ORDER BY agreement ASC
Go fiddle: http://sqlfiddle.com/#!2/c9ff0/7/0