Delete the duplicate values in the SUM with MySQL or SQL - mysql

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.

Related

Make a query to combine one result from two different tables with same / different columns

I am trying to make single query for a single result from two different tables. This table has same columns and also different columns.
Table Deposits
Name
D_Currency
D_Amount
Datetime
Michael
USD
500
2022-12-10 09:12:45
Susan
JPY
10000
2022-12-15 12:34:11
John
KRW
7000
2022-12-13 15:21:08
Table Withdrawal
Name
W_Currency
W_Amount
Datetime
Michael
USD
500
2022-12-11 09:55:32
Susan
EUR
800
2022-12-17 11:23:45
John
USD
300
2022-12-13 13:33:43
Result I want:
Name
D_Currency
D_Amount
W_Currency
W_Amount
Datetime
Michael
USD
500
2022-12-10 09:12:45
Michael
USD
500
2022-12-11 09:55:32
John
USD
300
2022-12-13 13:33:43
John
KRW
7000
2022-12-13 15:21:08
Susan
JPY
10000
2022-12-15 12:34:11
Susan
EUR
800
2022-12-17 11:23:45
I want all the columns from both tables, but the order is in Datetime.
I think I can use column Name for join, but not sure how to add Datetime.
First I tried join, which didn't work:
SELECT d.Name, d.D_currency, d.D_amount, w.W_currency, w.W_amount,
d.Datetime as date, w.Datetime as date
FROM Deposits d
JOIN Withdrawal w on w.Name = d.Name
ORDER BY date
I was thinking of UNION, but don't have the slightest idea how to even use it.
Please help.
In order to use the UNION operation, the requirement is that you need to have the exact same schema for the two tables you're applying it on. You can use the NULL values to fill the fields whose value you don't have, and rename the field with the corresponding field name you have in the expected output table.
SELECT Name, D_Currency, D_Amount,
NULL AS W_Currency, NULL AS W_Amount,
Datetime_
FROM Deposits
UNION ALL
SELECT Name, NULL AS D_Currency, NULL AS D_Amount,
W_Currency, W_Amount,
Datetime_
FROM Withdrawal
ORDER BY Name
Some remarks to take into account when applying a union operation:
Applying the union between two sets as we know it, is carried out by the UNION ALL operation. The difference between UNION and UNION ALL is that the former applies an aggregation to eliminate the duplicates too, if you have any. Since in your case you're not supposed to have duplicates, you can avoid stacking up an unnecessary operation.
The order of the fields over the two table you're carrying the union on is important. If the two tables don't have the same fields in the same order, the DBMS will throw a schema mismatch error.
The last ORDER BY clause will apply on the whole output of the union operation.
Check the demo here.

mysql query to identify groups of data based on timestmp

I have records of smartmeter in an mysql database.
Records in timestamp order looking in generall as follow:
key
timestamp
watt now
000001
2022-10-04-01-01-01
10
000002
2022-10-04-01-02-01
10
000003
2022-10-04-01-03-01
101
000004
2022-10-04-01-04-01
101
000005
2022-10-04-01-05-01
102
000006
2022-10-04-01-06-01
101
000007
2022-10-04-01-07-01
102
000008
2022-10-04-01-08-01
10
000009
2022-10-04-01-09-01
10
000010
2022-10-04-01-09-01
10
000011
2022-10-04-01-09-01
107
000012
2022-10-04-01-09-01
101
000013
2022-10-04-01-09-01
109
000014
2022-10-04-01-09-01
10
000015
2022-10-04-01-09-01
10
I want to identify the groups with bigger number (lets say > 100)
and give them an incresing id. Also I want to get per group the first and last key id
Result of query should look like this:
month
day
numbers of group
first id
last id
average watt
10
04
0
000003
000007
102
10
04
1
000011
0000013
105
Any help apreciated
You'll need something to identify them as a group. My first thought was using RANK() or DENSE_RANK() but after multiple tries, I couldn't find a way. Then I thought about using LAG() but still I'm stuck at how to re-identify the rows as new group. After testing many times, I come up with this suggestion:
WITH cte AS (
SELECT s1.*,
#n := COALESCE(IF(s1.skey=1,1,s2.skey), #n) As newGroup
FROM smartmeter s1
LEFT JOIN (
SELECT skey,
stimestamp,
watt,
LENGTH(watt) AS lenwatt,
LAG(LENGTH(watt)) OVER (ORDER BY skey) llwatt
FROM smartmeter) s2 ON s1.skey=s2.skey
AND lenwatt != llwatt)
SELECT MONTH(stimestamp) AS Month,
DAY(stimestamp) AS Day,
ROW_NUMBER() OVER (ORDER BY MIN(skey)) AS 'numbers of group',
MIN(skey) AS 'first id',
MAX(skey) AS 'last id',
AVG(watt) AS 'Average watt',
CEIL(AVG(watt)) AS 'Average watt rounded',
newGroup
FROM cte
WHERE watt >= 100
GROUP BY newGroup, MONTH(stimestamp), DAY(stimestamp)
By the way, I've changed some of your column names because key is actually a reserve word. Although you can use it as column name as long as you wrap it in backticks, I personally find it's a hassle to do it every time.
Ok, so my idea was to use LENGTH(watt) and ORDER BY skey in the LAG() function. Then I'll separate those rows where the length doesn't match and use that as a starting point for each new group. After that, I left join the result of that with smartmeter table. The next challenge is to assign each of the rows that doesn't match with previous skey value then I've found this answer and applied it into the cte.
Once those are done, I just write another query to fulfil your expected result. Although, some part of it is not exactly as what you expected.
Here's a demo fiddle

How to sum specific rows and columns in SQL?

pnr mnd pris
1 1 600
1 7 900
2 1 600
2 7 600
3 1 40
3 7 40
I have trouble how to sum specific rows on the columns. Looking at the above, the table is called travel and it has 3 columns:
pnr - Personal Number
mnd - Month
Pris - Price
So what I want is to sum total of the price for the a specific month, so in this case, it should be 1240 USD and month 1. For the month 7, it should be 1540 USD.
I have trouble to do the query correct. So far from I have tried is this:
SELECT t.rnr, t.mnd, SUM(t.pris)
FROM travel AS t
WHERE t.mnd = 1
The result I get is 3720 USD which I have no idea how the SQL managed to calculate this for me.
Appreciate if someone could please help me out!
For this you need to drop the pnr column from the output (it is not relevant and will cause your data to split) and add a GROUP BY:
SELECT t.mnd, SUM(t.pris)
FROM travel AS t
WHERE t.mnd = 1
GROUP BY t.mnd
Live demo: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=b34ec2bb9c077c2d74ffc66748c5c142
(The use of an aggregate function without grouping, as you've got now, is not a standard SQL feature and can often be turned off in MySQL. If turned on, you might not always get the result you expected/intended.)
just group your result with mnd column
SELECT t.mnd, SUM(t.pris)
FROM travel AS t
group by t.mnd

How to get the count of records with the highest date as a given date in mysql query

I have a table with 2 fields called clc_cs_id,clc_pt_nxt_rv_dtin my table. I am trying to get the count of clc_cs_id's having the highest date is 2016-06-25 from my below example. I have tried to give the max(clc_pt_nxt_rv_dt)='2016-06-25' in condition. But throwing invalid use of group by function error.
Sample data given below.
clc_cs_id clc_pt_nxt_rv_dt
--------- -------------------
2 25-06-2016 00:00:00
2 27-06-2016 00:00:00
3 17-06-2016 00:00:00
3 25-06-2016 00:00:00
3 29-06-2016 00:00:00
3 29-06-2016 00:00:00
4 18-06-2016 00:00:00
4 25-06-2016 00:00:00
5 25-06-2016 00:00:00
From the above i am trying to exclude clc_cs_id 3, because the highest date for that is 29.06.2016. The query which i tried is given below.
select count(clc_cs_id) from clc_case_dtls
where max(clc_pt_nxt_rv_dt) = date('2016-06-25')
group by clc_cs_id
If anybody can help, it will be very helpful for me.
Thanks in advance.
The expected output is
COUNT(clc_cs_id)
---------------
3
Your original query was not far off. I think you want to use HAVING to restrict each group in the query:
SELECT clc_cs_id, COUNT(clc_cs_id)
FROM clc_case_dtls
GROUP BY clc_cs_id
HAVING MAX(clc_pt_nxt_rv_dt) = STR_TO_DATE('2016-06-25', '%Y-%m-%d')
I also replaced your date() call with STR_TO_DATE().
If you want to get the total number of clc_cs_id values whose max date is 2016-06-25, then you can query the above query:
SELECT COUNT(*)
FROM
(
SELECT clc_cs_id, COUNT(clc_cs_id)
FROM clc_case_dtls
GROUP BY clc_cs_id
HAVING MAX(clc_pt_nxt_rv_dt) = STR_TO_DATE('2016-06-25', '%Y-%m-%d')
) t

MySQL, incrementing a row count by ascending dates (simple?)

I normally work in Access but cannot figure this logic within it. I'm now branching to MySQL in hopes i can do this.
Have table Visits with CUSTOMERID, VISITDATE
CUSTOMERID VISITDATE
1001 7/6/2015
2315 9/1/2015
2315 12/30/2014
9851 5/5/2013
9851 1/7/2014
9851 3/21/2014
I'd like to add a column called 'Visit Number' so I can label in ascending order each Customer's visitdate as his first, second, etc...
It would look like:
CUSTOMERID VISITDATE VISITNUMBER
1001 7/6/2015 1
2315 9/1/2015 1
2315 12/30/2014 2
9851 5/5/2013 1
9851 1/7/2014 2
9851 3/21/2014 3
It's an incrementation based on the ascending dates, but also grouped by CUSTOMERID.
Would seriously appreciate any tips on this. Thanks.
OK. So you have a query that you use to update your date whenever someone visits.
You want to cause an additional action at this point because this equates to an increment of visits.
if I'm not incorrect, a simple bundle of:
YOUR UPDATE SQL;
UPDATE mytable
SET visitnumber = visitnumber + 1
WHERE customerid = (the id of the user you are updating);