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

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);

Related

Combining between two tables in MySQL and getting the distinct answer

I know this has probably been asked before but I am trying to find the correct way to this and I have been struggling for the past week or so.
So we have two sets of data for example, one table is called 'Order Log' and another is called 'Customer Information'
and here are example of the two data set
NOTE: The order log will sometimes have order from the same customer twice
Order Log Table
Customer ID
Date
Order Number
Order Amount
sgcwi
2022-06-11
124
3
gbtfc
2022-07-09
12
4
crownwood
2022-04-08
123
1
kcsi
2022-02-24
543
1
ulsteri
2022-08-08
423
2
gbtfc
2022-07-08
1254
3
ulsteri
2022-04-08
345
2
kcsi
2022-07-13
64
1
crownwood
2022-07-04
55
1
Customer Information Table
Customer Name
Customer ID
Contact
Sagen Private
sgcwi
email
Granten Viel
gbtfc
phone
Crownwood LTD
crownwood
email
Kings College
kcsi
email
Ulster FC
ulsteri
phone
So what my question is, how do i write an sql query that gives me back the the last order for each customer from the Order Log table withhin a span of the last 6 Months and returns me back the customer name for each of those selected data from the customer Informationt table. like such
The Sql Query Return that i want
Customer Name
Customer ID
Date
Sagen Private
sgcwi
2022-06-11
Granten Viel
gbtfc
2022-06-11
Crownwood LTD
crownwood
2022-07-04
Kings College
kcsi
2022-07-13
Ulster FC
ulsteri
2022-08-08
so far I have figured out to get the result from the Log table that I gave to use the query
"SELECT DISTINCT orderLog.customerID FROM Order WHERE qslogv2.date >= DATE_ADD(NOW(), INTERVAL -3 MONTH);
But I am yet to figure out how do i connect the Customer Information table to this query so it returns me the appropriate customer name along with the query.
I tried using the above query that I mentioned and also tried the UNION keyword in MySQL but to my demise I was not able to get to a point where I got that desired result.
Use JOIN-statement combined with MAX + GROUP BY.
In JOIN you tell what columns match in the joined tables. In your case it is the Customer ID.
With GROUP BY, you divide the rows into sets (based on the customer) and then applies the MAX-function for each of those sets, so that you will get the latest date for each customer.
select
c.name,
c.id,
max(ol.date)
from customerInformation c
join orderLog ol on ol.customerID=c.id
where ol.date between date_sub(now(), interval 6 month) and now()
group by c.name, c.id

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

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.

MYSQL query - cross tab? Union? Join? Select? What should I be looking for?

Not sure what exactly it is I should be looking for, so I'm reaching out for help.
I have two tables that through queries I need to spit out one. the two tables are as follows:
Transactions:
TransactionID SiteID EmployeeName
520 2 Michael
521 3 Gene
TransactionResponse:
TransactionID PromptMessage Response PromptID
520 Enter Odometer 4500 14
520 Enter Vehicle ID 345 13
521 Enter Odometer 5427 14
521 Enter Vehicle ID 346 13
But what I need is the following, let's call it TransactionSummary:
TransactionID SiteID EmployeeName 'Odometer' 'VehicleID'
520 2 Michael 4500 345
521 3 Gene 5427 346
The "PromptID" column is the number version of "PromptMessage" so I could query off that if it's easier.
A good direction for what this query would be called is the least I'm hoping for. True extra credit for working examples or even using this provided example would be awesome!
For a predefined number of possible PromptID values you can use something like the following query:
SELECT t.TransactionID, t.SiteID, t.EmployeeName,
MAX(CASE WHEN PromptID = 13 THEN Response END) AS 'VehicleID',
MAX(CASE WHEN PromptID = 14 THEN Response END) AS 'Odometer'
FROM Transactions AS t
LEFT JOIN TransactionResponse AS tr
ON t.TransactionID = tr.TransactionID AND t.SiteID = tr.SiteID
GROUP BY t.TransactionID, t.SiteID, t.EmployeeName
The above query uses what is called conditional aggregation: a CASE expression is used within an aggregate function, so as to conditionally account for a subset of records within a group.

finding total and unique hits for each product

I have table structure as follows
id productid ip hittime
---------------------------------------------------------------------------
1 5 1.1.1.1 2011-05-03 06:55:11
2 5 1.1.1.1 2011-05-03 06:57:11
3 6 2.2.2.2 2011-05-03 07:30:00
4 4 1.1.1.1 2011-05-03 07:32:54
5 5 2.2.2.2 2011-05-03 07:55:00
Now I need query such that, it output me total and unique hits for each product
productid totalhits uniquehits
------------------------------------------------------------------
4 1 1
5 3 2
6 1 1
Criteria for
Total Hits = all the records that belong to particular product
Unique Hits = 2 hits are identified as unique hits if (1) IP is different or (2) for same ip, there is difference of 5 mins in hittime
How can I achieve this?
rMX was extremely close with his solution, it's quite clever. He should really get the credit, I just tweaked it slightly to add in a couple missing pieces:
select productid, count(*) totalhits,
count(distinct
concat(ip,
date_format(hittime, '%Y%m%d%H'),
round(date_format(hittime, '%i') / 5) * 5)
) uniquehits
from table
group by productid
Changes I made to rMX's idea:
Changed ceil() to round() because
ceil/floor will cause edge cases to
be treated improperly
Multiply the results of the round()
by 5. I think rMX meant to do this
and just forgot to type it.
EDIT: The multiplying by 5 really isn't necessary. My brain was just muddled. Changing ceil() to round() still matters though.
UPD>
select productid, count(*) totalhits,
count(distinct
concat(ip,
date_format(hittime, '%Y%m%d%H'),
ceil(date_format(hittime, '%i') / 5))
) uniquehits
from table
group by productid
I think, this should work. Sorry, had no time to test it.