How to reliably count preceding rows in MySQL? - mysql

I would like to know how to count preceding number of rows of a given row, in a given order by clause, in MySQL.
Also the rows may be inserted randomly, so auto_increment is unreliable.
MyAgenda - List
ID FROM TO
32 2017-09-26 12:35:00 2017-09-26 13:35:00
33 2017-10-10 12:35:00 2017-10-10 13:35:00
32 2017-10-17 12:35:00 2017-10-17 13:35:00
32 2017-10-24 12:35:00 2017-10-24 13:35:00
Like in this case, The rows are sorted by the "From" column, but apparently row 34 is inserted before row 36, but after sorting 36 is above 34, and if another row 37 is inserted it maybe above or below any row, or even at the top. So how can I reliably count the preceding number of rows above a given row, in a given order by clause?
Tried the subquery method but it is O(n^2) and will be painfully slow when the number of rows is large.

This counts records before record #36:
select count(*)
from mytable
where from_date < (select from_date from mytable where id = 36);

First I would suggest not to sort by one column only
try this
ORDER BY From, ID
about your question, not sure if i understood the question correctly but in that case this script may help
SELECT COUNT(*)
FROM your_table
WHERE From > #From
ORDER BY From, ID

Related

Delete the duplicate values in the SUM with MySQL or SQL

Hi I am doing a sum of a table, but the problem is that the table has duplicate rows, so I wonder how can I do the sum without duplicated rows:
The main table is this one:
folio
cashier_id
amount
date
0001
1
2500
2022-06-01 00:00:00
0002
2
10000
2022-06-01 00:00:00
0001
1
2500
2022-06-01 00:00:00
0003
1
1000
2022-06-01 00:00:00
If I sum that you can see that the first and the third row are duplicated, so when I do the sum it makes it wrong because, the result will be:
cashier_id
cash_amount
1
6000
2
10000
but it should be:
cashier_id
cash_amount
1
3500
2
10000
The query that I use to make the sum is this one:
SELECT `jysparki_jis`.`api_transactions`.`cashier_id` AS `cashier_id`,
SUM(`jysparki_jis`.`api_transactions`.`cash_amount`) AS `cash_amount`,,
COUNT(0) AS `ticket_number`,
DATE(`jysparki_jis`.`api_transactions`.`created_at`) AS `date`
FROM `jysparki_jis`.`api_transactions`
WHERE DATE(`jysparki_jis`.`api_transactions`.`created_at`) >= '2022-01-01'
AND (`jysparki_jis`.`api_transactions`.`dte_type_id` = 39
OR `jysparki_jis`.`api_transactions`.`dte_type_id` = 61)
AND `jysparki_jis`.`api_transactions`.`cashier_id` <> 0
GROUP BY `jysparki_jis`.`api_transactions`.`cashier_id`,
DATE(`jysparki_jis`.`api_transactions`.`created_at`)
How you can see the sum is this:
SUM(`jysparki_jis`.`api_transactions`.`cash_amount`).
I wonder how can I do the sum avoiding to duplicate the folio with same cashier_id?
I know that if I filter for the cashier_id and folio I can avoid the duplicate rows but I do not know how to do that, can you help me?
Thanks
Given your provided input tables, you can use the DISTINCT clause inside the SUM aggregation function to solve your problem:
SELECT cashier_id, SUM(DISTINCT amount)
FROM tab
GROUP BY cashier_id,
folio,
date
Check the demo here.
Then you can add up your conditions inside your WHERE clause to this query, and your aggregation on the "created_at" field (that should correspond to the "date" field of your sample table - I guess). This solution may give your the general idea.

Delete duplicate rows with lowest values in another column in mysql

I'm newbie, and I'm trying to delete duplicate rows with highest value in another column,
This is My database and result of below query
SELECT file_id,src,dst,durations,date_time, COUNT(*), MAX(durations) as
Max_durations
FROM C2
WHERE durations in (
SELECT max(durations)
FROM C2
GROUP BY src, dst
HAVING COUNT(*) >1)
GROUP BY src,dst
HAVING COUNT(*)>1
Now I want to remove Duplicate rows but keep rows that have maximum duration or equal Max_duration column and if have same duration delete one of them.
How can i do it...?
src
dst
duration
COUNT
Max_duration
12014504264
9726341011
464
20
684
12014504264
9726645434
320
8
875
12014556435
9726876431
765
4
900
12014576565
9726347656
43
7
600
12014508754
9726344537
233
2
233
12014764532
9726877654
655
2
54
12014587875
9726645443
1345
5
982
12014654536
9726766433
73
2
84
Assuming you are trying to actually delete rows from the table, not just have a query that omits certain rows:
To do this, just self-join with a row that would be preferred to the current one, so only rows where that is found are deleted:
delete C2
from C2
join C2 preferred on
preferred.src=C2.src and
preferred.dst=C2.dst and
preferred.durations >= C2.durations and
(preferred.durations > C2.durations or preferred.file_id < C2.file_id)
But to do this, you need some unique column to establish a precedence between multiple rows with the maximum duration; here I am using file_id and keeping the row with the lowest file_id.

How to Query the Same Data within a Table but the Output Row Positions are Different

I have a table inside my database just like the sample below and i would like to query the same data but in the Column 2 the positions of the data would be 1 row greater than the previous data.
P.S. Im actually making a system for a Electric Meter Reading and I need the Current(Column 1) and the Previous(Column 2) Data Reading, so that I could compute the total consumption of the Electric Meter. But I am having a hard time doing it. Any suggestions would be deeply appreciated. Thank You. :)
Example data:
Desired Query Output:
Keep in mind that SQL table rows have no inherent order. They're just bags of records.
You must order them based on some column value or other criterion. In your case I guess you want the most recent and the second most recent meter reading for each account. Presumably your reading table has columns something like this:
reading_id customer_id datestamp value
1 1122 2009-02-11 112
2 1234 2009-02-13 18
3 1122 2009-03-08 125
4 1234 2009-03-10 40
5 1122 2009-04-12 160
6 1234 2009-04-11 62
I guess you need this sort of result set
customer_id datestamp value previous
1122 2009-03-08 125 112
1122 2009-04-12 160 125
1234 ...etcetera.
How can you get this? For each row in the table, you need a way to find the previous reading for the same customer: that is, the row with
the same customer id
the latest datestamp that occurs before the current datestamp.
This is a job for a so-called correlated subquery. Here's the query, with its subquery. (https://www.db-fiddle.com/f/hWGAbq4uAbA5f15j7oZY9o/0)
SELECT aft.customer_id,
aft.datestamp,
( SELECT bef.value
FROM r bef /* row from table.... */
WHERE bef.datestamp < aft.datestamp /* with datestamp < present datestamp */
AND bef.customer_id = aft.customer_id /* and same customer id */
ORDER BY bef.datestamp DESC /* most recent first */
LIMIT 1 /* only most recent */
) prev,
aft.value
FROM r aft
ORDER BY aft.customer_id, aft.datestamp
Notice that dealing with the first reading for each customer takes some thought in your business process.

Optimising a mysql statement

i have a table with around 1 128 910 rows and now my SQL statement is starting to run very slow.
My table looks like this:
SU_Id SU_User SU_Skill SU_Value SU_Date
int(10) int(10) int(10) float int(10)
1 1 23 45.34 1300978612
2 1 23 48.51 1300978865
3 1 23 47.21 1300979203
4 3 23 61.01 1300979245
5 2 23 38.93 1300979412
6 1 17 12.76 1300979712
7 2 23 65.30 1300979998
As seen in SU_Skill a user can have more then one entry with the same skill number. SU_Value hold the value of a skill, it can go up and down. SU_Date holds the date when a value was added.
I want a SQL statement that selects the 20 currently highest values of a skill. The following SQL statement is what i use today but it is slow and i think there is a better way of doing it.
SELECT DISTINCT SU_User AS Player,
(SELECT SU_Value FROM WOU__SkillUploads WHERE SU_User = Player AND SU_Skill = 23 ORDER BY SU_Date DESC LIMIT 1) AS Value
FROM WOU__SkillUploads
WHERE SU_Skill = 23
ORDER BY Value DESC LIMIT 20
Is there a faster way? Thanks for reading my question!
Sub-selects are very slow, especially in the way you're using this.
Rewrite this as a JOIN. In this case, because you want all records from SkillUploads where SU_SKILL = 23, this should probably be a RIGHT JOIN.
Can the same user be in the results multiple times? This may work for you.
SELECT SU_USER, MAX(SU_VALUE)
FROM WOU_SKILLUploads
WHERE SU_SKILL=23
GROUP BY SU_USER
ORDER BY MAX(SU_VALUE) DESC
LIMIT 20

How to show every max value in mysql?

I've multiple values with different timestamps like the following:
10 01:01:00
20 01:35:00
30 02:10:00
05 02:45:00
12 03:05:00
21 03:30:00
10 04:06:00
40 05:15:00
I don't have a column with which I can group by and find max. I want to get the records with max values like 30,21, and 40. The data is always in this format, like value increasing and then starts from zero again. What query will help me to find these records?
To clarify, it's sorted by the timestamp, and I want to get the timestamps for the local maxima, the rows where the next row has a lesser value:
value tmstmp
----- --------
10 01:01:00
20 01:35:00
30 02:10:00 <-- this one since next value is 5 (< 30).
05 02:45:00
12 03:05:00
21 03:30:00 <-- this one since next value is 10 (< 21).
10 04:06:00
40 05:15:00 <-- this one since next value is 40 (< infinity).
Somehow your question is not clear to me.
Assume that first column name is "value" and second column name is "timestamp".
Select Max(value) from group by timestamp.
This answer might be a bit late, however i think i have found the solution
SELECT * FROM temp t1 WHERE value >
IFNULL(
(SELECT value FROM temp t2
WHERE t2.tmstmp > t1.tmstmp ORDER BY t2.tmstmp ASC limit 1),
-1
)
ORDER BY tmstmp ASC
To clarify:
I find the values where the value is greater than the next value in the row.
To also get the final value I have added an IFNULL around the subquery to make sure the subquery will then return -1
The only problem i see is when the time goes over to the next day, that's why i hope you can have a date appended to it as well.
Hopefully this will still help others