Confusing ordering of user variable counter in MariaDB - mysql

Recently I've updated a server and switched from MySQL to MariaDB.
One query behaves now differently and I do not understand why.
Please enlighten me.
This is my current version
mariadb --version
mariadb Ver 15.1 Distrib 10.6.11-MariaDB, for debian-linux-gnu (x86_64) using EditLine wrapper
The actual query is very long, but here is a condensed form of my problem. I need to update a variable test, which is updated for each row after all rows have been ordered.
The actual update is more complex, but should not matter here:
#stockMass := #stockMass +
CASE
WHEN `u`.`context` = 'purchase' AND `u`.`status` != 'canceled' THEN `u`.`mass`
WHEN `u`.`context` = 'sale' AND `u`.`status` != 'canceled' THEN -`u`.`mass`
WHEN `u`.`context` = 'massAdjustment' THEN `u`.`mass`
WHEN `u`.`context` = 'splitIn' THEN `u`.`mass`
WHEN `u`.`context` = 'splitOut' THEN -`u`.`mass`
ELSE 0
END AS `stock`
SET #test := 0;
SELECT
*,
#test := #test + 1 AS `test`
FROM (
SELECT
`g_sales`.`sale`,
`g_sales`.`date`
FROM
`g_sales`
ORDER BY
`g_sales`.`date`
) AS `t` ORDER BY `t`.`date`;
results in
+------+------------+------+
| sale | date | test |
+------+------------+------+
| 106 | 2019-06-19 | 2703 |
| 85 | 2019-10-11 | 2685 |
| 81 | 2019-11-12 | 2681 |
| 96 | 2019-12-09 | 2695 |
| 104 | 2020-03-26 | 2701 |
| 87 | 2020-04-06 | 2687 |
| 94 | 2020-05-15 | 2693 |
| 107 | 2020-05-18 | 2704 |
| 98 | 2020-05-28 | 2697 |
| 103 | 2020-05-28 | 2700 |
| ... | .......... | .... |
+------+------------+------+
In MySQL test started at 1 and was incremented by one in each row.
Adding a limit to the inner SELECT gets me a similar result in MariaDB.
SET #test := 0;
SELECT
*,
#test := #test + 1 AS `test`
FROM (
SELECT
`g_sales`.`sale`,
`g_sales`.`date`
FROM
`g_sales`
ORDER BY
`g_sales`.`date`
LIMIT 10 OFFSET 0
) AS `t`;
which results in
+------+------------+------+
| sale | date | test |
+------+------------+------+
| 106 | 2019-06-19 | 1 |
| 85 | 2019-10-11 | 2 |
| 81 | 2019-11-12 | 3 |
| 96 | 2019-12-09 | 4 |
| 104 | 2020-03-26 | 5 |
| 87 | 2020-04-06 | 6 |
| 94 | 2020-05-15 | 7 |
| 107 | 2020-05-18 | 8 |
| 98 | 2020-05-28 | 9 |
| 103 | 2020-05-28 | 10 |
+------+------------+------+
How can I get this result in MariaDB without adding a limit to the inner SELECT?
And why do I get this result when adding the LIMIT?

Related

Select timeline in MySQL database

This is my MySQL table.
+-----------+-------------+---------------------+
| element | status | hour |
+-----------+-------------+---------------------+
| 18 | Available | 2020-01-19 14:23:49 |
| 18 | Unavailable | 2019-09-13 18:19:47 |
| 18 | Available | 2019-09-13 18:18:49 |
| 18 | Unavailable | 2019-09-09 08:22:45 |
| 19 | Available | 2019-09-07 19:13:56 |
| 19 | Available | 2019-09-03 18:13:49 |
+-----------+-------------+---------------------+
Normally the timeline of rows in this MySQL table for each element status is unavailable / available.
But it happened that for element number 19 the timeline of rows in status is available / available :
+----------+-------------+---------------------+
| element | status | hour |
+----------+-------------+---------------------+
| 19 | Available | 2019-09-07 19:13:56 |
| 19 | Available | 2019-09-03 18:13:49 |
+----------+-------------+---------------------+
is this means anomaly.
I need to intercept these cases that is, all the rows for each element status when the timeline is available / available.
How to do resolve this ?
Please can you help me ?
#Edit 01
+-----------+-------------+---------------------+---------+
| element | status | hour | ID |
+-----------+-------------+---------------------+---------+
| 18 | Available | 2020-01-19 14:23:49 | 6 |
| 18 | Unavailable | 2019-09-13 18:19:47 | 5 |
| 18 | Available | 2019-09-13 18:18:49 | 4 |
| 18 | Unavailable | 2019-09-09 08:22:45 | 3 |
| 19 | Available | 2019-09-07 19:13:56 | 2 |
| 19 | Available | 2019-09-03 18:13:49 | 1 |
+-----------+-------------+---------------------+---------+
Based on your originally published sample data you can use a sub query to take a look at the next and previous status then test
select s.element,s.hour,s.`status`
from
(
select t.*,
(select concat(t1.status,',',t1.hour) from t t1
where t1.element = t.element and t1.hour < t.hour
order by t1.element,t1.hour desc limit 1) prev,
(select concat(t1.status,',',t1.hour) from t t1
where t1.element = t.element and t1.hour > t.hour
order by t1.element,t1.hour limit 1) nxt
from t
) s
where s.status = substring_index(s.nxt,',',1) or
s.status = substring_index(s.prev,',',1)
;

MYSQL COUNT(column) returns multiple lines unexpectedly

I have two tables:
1. SELECT * FROM gas_trades_bids;
+----+---------+----------+--------+------------+------------+
| id | user_id | claim_id | amount | lots_value | timestmp |
+----+---------+----------+--------+------------+------------+
| 5 | 9 | 11 | 60 | NULL | 1571317861 |
| 6 | 9 | 11 | 100 | NULL | 1571656888 |
| 7 | 9 | 11 | 50 | NULL | 1571727353 |
| 8 | 9 | 11 | 50 | NULL | 1571918296 |
+----+---------+----------+--------+------------+------------+
4 rows in set (0.00 sec)
2. SELECT * FROM gas_trades_offers;
+----+---------+----------+--------+------------+----------+------------+
| id | user_id | claim_id | amount | lots_value | accepted | timestmp |
+----+---------+----------+--------+------------+----------+------------+
| 8 | 9 | 11 | 33 | 22 | NULL | 1571918576 |
| 9 | 9 | 11 | 33 | 22 | 1 | 1571918576 |
| 10 | 9 | 11 | 33 | 22 | 1 | 1571918576 |
+----+---------+----------+--------+------------+----------+------------+
3 rows in set (0.01 sec)
The goals are:
Count the amount of the rows where gas_trades_bids.claim_id = gas_trades_offers_claim_id and gas_trades_bids.claim_id = 11 and gas_trades_bids.user_id = 11
Get the sum of the column gas_trades_offers.lots_value values
To reach this I tried to run:
SELECT COUNT(bids.id) amount, SUM(offers.lots_value)
FROM gas_trades_offers offers, (SELECT * FROM gas_trades_bids) bids
WHERE bids.user_id = 9
AND bids.user_id = offers.user_id
But I've got the multiple rows:'
+--------+------------------------+
| amount | SUM(offers.lots_value) |
+--------+------------------------+
| 3 | 66 |
| 3 | 66 |
| 3 | 66 |
| 3 | 66 |
+--------+------------------------+
4 rows in set (0.01 sec)
What do I do in the wrong way?
I have expected to get only:
+--------+------------------------+
| amount | SUM(offers.lots_value) |
+--------+------------------------+
| 3 | 66 |
+--------|------------------------|
I don't need to use GROUP BY!
Is it exactly what you need? Hope that this query can work well.
SELECT COUNT(offers.id) amount,
SUM(offers.lots_value)
FROM gas_trades_offers offers
WHERE offers.user_id = 9 and offers.claim_id = 11
AND exists (SELECT id FROM gas_trades_bids bids WHERE bids.claim_id = offers.claim_id and bids.user_id = offers.user_id)
Try this:
SELECT COUNT(bids.id) amount,
SUM(offers.lots_value)
FROM gas_trades_offers offers
JOIN gas_trade_bids bids ON bids.user_id = offers.user_id
WHERE offers.user_id = 9;

Return multi columns result from single table with zero values

I have a single table like :
mysql> select RefID,State,StartTime,EndTime from execReports limit 5;
+--------------------------------------+-----------+---------------------+---------------------+
| RefID | State | StartTime | EndTime |
+--------------------------------------+-----------+---------------------+---------------------+
| 00019a52-8480-4431-9ad2-3767c3933627 | Completed | 2016-04-18 13:45:00 | 2016-04-18 13:45:01 |
| 00038a8a-995e-4cb2-a335-cb05d5b3e92d | Aborted | 2016-05-03 04:00:00 | 2016-05-03 04:00:02 |
| 001013f8-0b86-456f-bd59-a7ef066e565f | Completed | 2016-04-14 03:30:00 | 2016-04-14 03:30:11 |
| 001f8d23-3022-4271-bba0-200494de678a | Failed | 2016-04-30 05:00:00 | 2016-04-30 05:00:02 |
| 0027ba42-1c37-4e50-a7d6-a4e24056e080 | Completed | 2016-04-18 03:45:00 | 2016-04-18 03:45:02 |
+--------------------------------------+-----------+---------------------+---------------------+
I can extract the count of exec for each state with :
mysql> select distinct State,count(StartTime) as nbExec from execReports group by State;
+-----------+--------+
| State | nbExec |
+-----------+--------+
| Aborted | 3 |
| Completed | 14148 |
| Failed | 49 |
+-----------+--------+
4 rows in set (0.02 sec)
I can extract the count of exec for each week with :
mysql> select distinct extract(week from StartTime) as Week, count(StartTime) as nbExec from execReports group by Week;
+------+--------+
| Week | nbExec |
+------+--------+
| 14 | 1317 |
| 15 | 3051 |
| 16 | 3066 |
| 17 | 3059 |
| 18 | 3059 |
| 19 | 652 |
+------+--------+
6 rows in set (0.01 sec)
But I would like to extract a crossing table like :
+------+---------+-----------+--------+---------+---------+
| Week | nbExec | Completed | Failed | Running | Aborted |
+------+---------+-----------+--------+---------+---------+
| 14 | 1317 | 1312 | 3 | 1 | 1 |
| 15 | 3051 | 3050 | 1 | 0 | 0 |
| 16 | 3066 | 3060 | 3 | 2 | 1 |
| 17 | 3059 | 3058 | 0 | 1 | 0 |
| 18 | 3059 | 3057 | 1 | 0 | 1 |
| 19 | 652 | 652 | 0 | 0 | 0 |
+------+---------+-----------+--------+---------+---------+
I'm stuck on this for a few days. Any help appreciated.
Best regards
select extract(week from StartTime) as Week, count(StartTime) as nbExec,
sum(if(state="Completed",1,0)) Completed,
sum(if(state="Failed",1,0)) Failed,
sum(if(state="Aborted",1,0)) Aborted
from execReports group by Week;
demo
You can join multi tables for this. If you want for dynamic row to column, check this: MySQL pivot row into dynamic number of columns
SELECT
a.week,
count(a.StartTime) as nbExec,
count(b1.StartTime) as Completed,
count(b2.StartTime) as Failed,
count(b3.StartTime) as Running,
count(b4.StartTime) as Aborted,
FROM execReports a
LEFT JOIN execReports b1 ON a.refID = b1.refID and b1.state ='Completed'
LEFT JOIN execReports b2 ON a.refID = b2.refID and b2.state ='Failed'
LEFT JOIN execReports b3 ON a.refID = b3.refID and b3.state ='Running'
LEFT JOIN execReports b4 ON a.refID = b4.refID and b4.state ='Aborted'
GROUP BY 1

MySQL combine results from UNION of same-scheme tables

There are two tables with the same structure: 'imsc_storage_users' & 'imsc_storage_users_archive'.
My current SELECT/UNION:
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION DISTINCT
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`
ORDER BY `correct` DESC,`minutes` ASC
I'm getting these results:
+--------------+---------------------+-----------+---------+---------+------+---------+
| cli | ts | questions | answers | correct | last | minutes |
+--------------+---------------------+-----------+---------+---------+------+---------+
| 111111111111 | 2011-12-22 11:13:57 | 30 | 29 | 14 | 30 | 1305.47 |
| 222222222222 | 2011-12-15 13:39:16 | 26 | 24 | 13 | 24 | 15.67 |
| 333333333333 | 2011-12-15 13:39:39 | 26 | 25 | 11 | 25 | 15.18 |
| 444444444444 | 2011-12-15 13:39:39 | 25 | 21 | 11 | 25 | 280.53 |
| 111111111111 | 2011-12-22 11:13:57 | 25 | 21 | 10 | 25 | 373.87 |
| 555555555555 | 2011-12-19 15:46:15 | 11 | 10 | 5 | 10 | 3.8 |
| 666666666666 | 2011-12-15 13:39:16 | 14 | 10 | 4 | 10 | 321.64 |
| 777777777777 | 2011-12-19 08:34:36 | 15 | 11 | 4 | 13 | 474.66 |
Notice that '111111111111' appears twice?
I want it to be combined, so in the results set I get one row of '111111111111' which combines/sums all fields; 'questions' =>> 55.... etc'.
What would be the correct SQL?
Performance are NOT of an issue here.
Thank you!
SELECT `cli`,max(`ts`) AS ts, sum(`questions`) as questions, sum(`answers`) as answers,sum(`correct`) as correct,sum(`last`) as last,sum(`minutes`) as minutes
FROM (
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION ALL
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`
) AS baseview
GROUP BY cli
ORDER BY `correct` DESC,`minutes` ASC
Try:
SELECT `cli`,
`ts`,
sum(`questions`),
sum(`answers`),
sum(`correct`),
sum(`last`),
sum(`minutes`)
FROM (SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION ALL
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`) V
group by `cli`, `ts`
ORDER BY 5 DESC, 7 ASC

MySQL add extra column on result based on another query

I have following Problem
SELECT * from map_user_sticker WHERE map_user_sticker.user_id = 7;
+----+---------+------------+
| id | user_id | sticker_id |
+----+---------+------------+
| 35 | 7 | 55 |
| 3 | 7 | 30 |
| 32 | 7 | 49 |
| 33 | 7 | 52 |
| 34 | 7 | 43 |
| 36 | 7 | 50 |
+----+---------+------------+
6 rows in set (0.00 sec)
SELECT * FROM sticker;
+----+--------------------------------------------------+
| id | word |
+----+--------------------------------------------------+
| 40 | I love Sonal |
| 41 | Add User to Database |
| 39 | This is a dream Project |
| 33 | Narendra Sisodiya |
| 34 | Sourabh Parmar |
| 30 | Sonal Sisodiya |
| 42 | I love India |
| 43 | I love Linux |
| 44 | I hate Congress |
| 45 | I love jQuery |
| 48 | Modi will be the PM |
| 47 | Ramdev Baba is my Super Hero |
| 49 | हिन्दी से प्यार है |
| 50 | Linux is better then Windows |
| 52 | I am from Sehore |
| 55 | I have 2 little kids - sadu and sonu |
+----+--------------------------------------------------+
16 rows in set (0.00 sec)
I basically want to generate Result like
+----+--------------------------------------------------+----------+
| id | word | present |
+----+--------------------------------------------------+----------+
| 40 | I love Sonal | 0 |
| 41 | Add User to Database | 0 |
| 39 | This is a dream Project | 0 |
| 33 | Narendra Sisodiya | 0 |
| 34 | Sourabh Parmar | 0 |
| 30 | Sonal Sisodiya | 1 |
| 42 | I love India | 0 |
| 43 | I love Linux | 1 |
| 44 | I hate Congress | 0 |
| 45 | I love jQuery | 0 |
| 48 | Modi will be the PM | 0 |
| 47 | Ramdev Baba is my Super Hero | 0 |
| 49 | हिन्दी से प्यार है | 1 |
| 50 | Linux is better then Windows | 1 |
| 52 | I am from Sehore | 1 |
| 55 | I have 2 little kids - sadu and sonu | 1 |
+----+--------------------------------------------------+----------+
16 rows in set (0.00 sec)
Please Help me !!
I want to generate a extra column called "present", based on following condition
If sticker_id from query1 == id from query 2 then present = 1
else present = 0
Here the Answer I was wanted to get !
Answer 1 -
SELECT s.* , IF(FIND_IN_SET(7,(GROUP_CONCAT(m.user_id))) != 0 , 1,0) as present, COUNT(m.user_id) as totalUsers
FROM sticker s
LEFT JOIN map_user_sticker m
ON s.id = m.sticker_id
GROUP BY id;
Answer 2 -
SELECT id,word, (case when 7 in (select user_id from map_user_sticker WHERE map_user_sticker.sticker_id=sticker.id) then 1 else 0 end) as present
from sticker;
I don,t know which one is fast and better
Try this:
select id,word,
case(when id in (select sticker_id from map_user_sticker) then 1 else 0 end)
as present from sticker;
Hope, this will help:
SELECT sticker.id, sticker.word, (IF(sticker_id IS NULL, 0, 1)) AS present FROM sticker LEFT JOIN map_user_sticker ON (sticker.id = map_user_sticker.sticker_id)
Try this query -
SELECT s.*, IF(COUNT(m.sticker_id) > 0, 1, 0) present FROM sticker s
LEFT JOIN map_user_sticker m
ON s.id = m.sticker_id
GROUP BY
s.id;
Is this what you want?
SELECT s.*, IF(m.sticker_id IS NULL, 0, 1) present FROM sticker s
LEFT JOIN map_user_sticker m
ON s.id = m.sticker_id
WHERE m.user_id = 7;