MySQL + ChatJS: How to group duplicated values by "day()"? - mysql

I know there're lots of possible duplicates similar to this question, I tested all I could find but I still have an issue understanding the logic of the query...
I have a bar chart which I wanna connect it to the query that showcases how many "seatbelt", "Speeding", etc violations happened per day.
The query I have now is:
select violationType as 'Violations', count( DISTINCT violationType) as 'Total', day(violationDateTime) as 'Day' from traffic_violations group by day(violationDateTime);
The result:
Do you think the result is correct? because what I see is that "wrong parking" is repeated by day, yes I know it showcases how many of wrong parking happened on day 1, 2, 3 but what about "Speeding"? It didn't happened in day 1, nor 2,3?
Basically I want to create a daily chart in the dashboard. Starts at 0 in the beginning of the day and counts up the traffic violations until the end of the day then resets the next day.
I also tried this:
select count(id) as 'Total', violationType as 'Violation', violationDateTime as 'Date' from traffic_violations group by violationType, day(violationDateTime);
results in:
Which I think is more correct than the above?

Related

Sql to get number of hours per user per day

A table 'Log' has the below columns:
SystemName
User
Datetime - it's a timestamp
Status - has the values Start or Stop.
I need to write a query which will give me :
Number of hours spent per user per day on system X.
Please see example data below:
X, Amit, 05/01/2019 08:45:00, Start
X, Amit, 05/03/2019 13:25:00, Stop
X, Dave, 05/01/2019 09:10:35, Start
X, Dave, 05/01/2019 17:35:42, Stop
Output:
Amit,05/01/2019, 15h
Amit,05/02/2019, 24h
Amit,05/03/2019, 9h
Dave,05/01/2019, 8h
My approach till now :
I was thinking I could use lead or lag to get the consecutive times in the same row. But in the case of user Amit that spans across multiple days. Also there could be a user who has started and stopped multiple times on the same day. Even if I do that how could I generate hours for the dates amidst the range. Can you please help me.
This should work. You will only get Hours spent if both Start and Stop status exists for a user in a single day.
SELECT SystemName,[user],
CONVERT(varchar, CAST(Datetime AS DATETIME), 1) Datetime,
DATEDIFF
(
HH,
MAX(CASE WHEN Ststus = 'Start' THEN [Datetime] ELSE NULL END ),
MAX(CASE WHEN Ststus = 'Stop' THEN Datetime ELSE NULL END )
)HourSpent
FROM your_table A
GROUP BY SystemName,[User],
CONVERT(varchar, CAST(Datetime AS DATETIME), 1)
Since the output consists of one row per User + Day, then you would need to JOIN the data to a calendar table of dates.
You would need a way to extract the Start and Stop timestamp pairs for a given user, join it to the calendar table, then count the number of hours on that day that are between the start and stop times. (The hour count could be use a User Defined Function.
That's pretty complex. Frankly, I would rather write a Python program to parse the data rather than doing it via SQL. It would be very simple:
Read start line
Read end line
Loop through days, outputting hours per day (quite simple in Python)
Sometimes the best hammer is a spanner. (Translation: Sometimes a different tool is better.)

MySQL Group By Order and Count(Distinct)

What is the best way to think about the Group By function in MySQL?
I am writing a MySQL query to pull data through an ODBC connection in a pivot table in Excel so that users can easily access the data.
For example, I have:
Select
statistic_date,
week(statistic_date,4),
year(statistic_date),
Emp_ID,
count(distict Emp_ID),
Site
Cost_Center
I'm trying to count the number of unique employees we have by site by week. The problem I'm running into is around year end, the calendar years don't always match up so it is important to have them by date so that I can manually filter down to the correct dates using a pivot table (2013/2014 had a week were we had to add week 53 + week 1).
I'm experimenting by using different group by statements but I'm not sure how the order matters and what changes when I switch them around.
i.e.
Group by week(statistic_date,4), Site, Cost_Center, Emp_ID
vs
Group by Site, Cost_Center, week(statistic_date,4), Emp_ID
Other things to note:
-Employees can work any number of days. Some are working 4 x 10's, others 5 x 8's with possibly a 6th day if they sign up for OT. If I sum the counts by week, I get anywhere between 3-7 per Emp_ID. I'm hoping to get 1 for the week.
-There are different pay code per employee so the distinct count helps when we are looking by day (VTO = Voluntary Time Off, OT = Over Time, LOA = Leave of Absence, etc). The distinct count will show me 1, where often times I will have 2-3 for the same emp in the same day (hits 40 hours and starts accruing OT then takes VTO or uses personal time in the same day).
I'm starting with a query I wrote to understand our paid hours by week. I'm trying to adapt it for this application. Actual code is below:
SELECT
dkh.STATISTIC_DATE AS 'Date'
,week(dkh.STATISTIC_DATE,4) as 'Week'
,month(dkh.STATISTIC_DATE) as 'Month'
,year(dkh.STATISTIC_DATE) as 'Year'
,dkh.SITE AS 'Site ID Short'
,aep.LOC_DESCR as 'Site Name'
,dkh.EMPLOYEE_ID AS 'Employee ID'
,count(distinct dkh.EMPLOYEE_ID) AS 'Distinct Employee ID'
,aep.NAME AS 'Employee Name'
,aep.BUSINESS_TITLE AS 'Business_Ttile'
,aep.SPRVSR_NAME AS 'Manager'
,SUBSTR(aep.DEPTID,1,4) AS 'Cost_Center'
,dkh.PAY_CODE
,dkh.PAY_CODE_SHORT
,dkh.HOURS
FROM metrics.DAT_KRONOS_HOURS dkh
JOIN metrics.EMPLOYEES_PUBLIC aep
ON aep.SNAPSHOT_DATE = SUBDATE(dkh.STATISTIC_DATE, DAYOFWEEK(dkh.STATISTIC_DATE) + 1)
AND aep.EMPLID = dkh.EMPLOYEE_ID
WHERE dkh.STATISTIC_DATE BETWEEN adddate(now(), interval -1 year) AND DATE(now())
group by dkh.SITE, SUBSTR(aep.DEPTID,1,4), week(dkh.STATISTIC_DATE,4), dkh.STATISTIC_DATE, dkh.EMPLOYEE_ID
The order you use in group by doesn't matter. Each unique combination of the values gets a group of its own. Selecting columns you don't group by gives you somewhat arbitrary results; you'd probably want to use some aggregation function on them, such as SUM to get the group total.
Grouping by values you derive from other values that you already use in group by, like below, isn't very useful.
week(dkh.STATISTIC_DATE,4), dkh.STATISTIC_DATE
If two rows have different weeks, they'll also have different dates, right?

Counting hours using MySQL

I'm creating simple project where I count the employee attendance and other things
when employee late on work ,I have to enter the delay time, example
employee came to work late by 30 min, so I will enter on the field 30:00 or 00:30:00 , in the end of each month , week, or day, I want to calculate the time, such as 30 min + 1H + 25 min and in the end of each month I will get the total of all that hours and minutes on the report, the report will show me the average and the sum of that time.
the following fields ( Timing Logged in Duration , Total Talking Time, Work , Time Not ready Time ) I want to calculate the hours and minutes.
what I’m getting in the report is showing the SUM of the hours I entered as time with AM/PM which is not what I’m looking for.
this is MySQL query
SELECT
ID,
`Date`,
`Shift Time`,
`In charge`,
`Agent Name`,
Attendance,
Timing,
`Logged in Duration`,
`Total Talking Time`,
`Work Time`,
`Not ready Time`,
`Calls Handled`,
RNA,
`Shift Calls Presented`,
`Shift Calls Handled`,
`HD Calls Abandoned`,
`Upload Your Report`
FROM `shift report`
I thought I would post you the answer in the perspective of summing up time value releated issues developers, users have face so far. It's not just about formatting.
You may or may not have noticed that there's posibility sum of your total time can be miscalculated by the engine. Further mysql engine could return null although you have values.
When you are adding/aggregating time values it is converted as a number and results will be in number format. If you attempt to adding up time values like the following:
e.g. 01:38:50, 03:40:25 --> should ideally result in 05:19:15
If you do Sum(the above two) --> you get a number
If you use CAST(Sum(the above two) AS TIME) --> you get null
There are two other possibilities showed in the my code snippet.
Sample code reference. It will show you the different results that we just discussed. As for now, it seems like three way formatting could help.
time_format(sec_to_time(sum(time_to_sec(logged_duration))),'%h:%i:%s') total_log_duration
The bug reported to MySQL is not rectified yet.

Is it possible to create multi-tiered WHERE statements in mySQL

I'm currently developing a program that will generate reports based upon lead data. My issue is that I'm running 3 queries for something that I would like to only have to run one query for. For instance, I want to gather data for leads generated in the past day
submission_date > (NOW() - INTERVAL 1 DAY)
and I would like to find out how many total leads there were, and how many sold leads there were in that timeframe. (sold=1 / sold=0). The issue comes with the fact that this query is currently being done with 2 queries, one with WHEREsold= 1 and one with WHEREsold= 0. This is all well and good, but when I want to generate this data for the past day,week,month,year,and all time I will have to run 10 queries to obtain this data. I feel like there HAS to be a more efficient way of doing this. I know I can create a mySQL function for this, but I don't see how this could solve the problem.
Thanks!!
Why not GROUP BY sold so you get the totals for sold and not sold
One way to do is to exploit the aggregate functions (usually SUM and COUNT help you the most in this situation) along with MySQL's IF() function.
For example, you could use a query such as:
SELECT
SUM(IF(sold = 1, sold, 0)) AS TotalSold,
SUM(IF(sold = 0, sold, 0)) AS TotalUnsold,
SUM(IF(submission_date > (NOW() - INTERVAL 1 WEEK)
AND sold = 1, sold, 0) AS TotalSoldThisWeek
FROM ...
WHERE ...
The condition (e.g. sold = 1) could be as complex as you want by using AND and OR.
Disclamer: code wasn't tested, this was just provided as an example that should work with minor modifications.

Query by month from date field

I have a set of Access d/b's grouped already by year. within a given year, I have a field caleld REPORTDATE which is a standard mm/dd/yyyy field. However, I need to produce queries that return data by the month. For example, I just want to see records for Jan, recs for Feb, Recs for March, etc., so that I can sum them and work wwith thm.
Do I use an expression in the query design view Criteria field?
Thanks in advance.
I just want to see records for Jan, recs for Feb, Recs for March, etc., so that I can sum them and work wwith thm.
You can do all of that in one sql statement:
select month(reportdate), sum( the column you wish to sum )
from tablename
group by month(reportdate);
BUT WAIT THERE'S MORE!
Further say that there are several salepersons selling stuff, and you wish to show each salesperson's sales by month
select month(reportdate), salesperson, sum( the column you wish to sum )
from tablename
group by month(reportdate), salesperson;
That shows the sum per month per salesperson.
You know the Germans always make good stuff!
What it you wanted to see the same sums, but rtaher than comparing salespeople against each other in each month, you wanted to compare, for each salesperson, how they did from one month to another?
Just reverse the order of the group by:
select month(reportdate), saleperson, sum( the column you wish to sum )
from tablename
group by salesperson, month(reportdate);
Tacos, Fettuccini, Linguini, Martini, Bikini, you're gonna love my nuts!
The power of SQL! As seen on TV! Order now!
"select month(reportdate), sum( the column you wish to sum )from tablenamegroup by month(reportdate);" THIS IS VERY HELPFUL, THANK YOU. AND YOU ARE HILARIOUS. HOWEVER, can you clarify for me where the heck this code goes?! In the expresison Builder or what? Thank you SO much. – rick (19 mins ago)
In Access, I think from the graphical Query Builder thing's menu, select edit|SQL, and just type. And never go back to graphical!
You're a hard-charging forward-thinking entrepreneurially-minded man on the move! This is not your father's Oldsmobile! You wouldn't use an on-screen keyboard to type a document, dragging and dropping letters on the page, would you?! So why do that to build a SQL Query? Get into SQL! AS SEEN ON TV! All the cool kids and hep cats are doin' it! Order NOW!
You can use format, for example:
Format([REPORTDATE],"mmm yy")
Or Month:
SELECT * FROM Table WHERE Month([REPORTDATE]) = 10
An outline of query that may suit, paste this into the SQL view of
the query design window, changing table to the name of your table:
SELECT Format([REPORTDATE],"yyyy mm"), Count([ReportDate])
FROM Table
GROUP BY Format([REPORTDATE],"yyyy mm")
I wouldn't do this in the report's recordsource. I'd make the recordsource a regular SELECT statement and use the report's sorting/grouping. If you group on a date field (one that is really date type), you get the choice to GROUP ON:
Each Value (default)
Year
Qtr
Month
Week
Day
Hour
Minute
I think this is faster than a GROUP BY on a function, but someone who was interested should actually try it.
Certainly if your SELECT with GROUP BY has no WHERE clause, it's going to be a lot more efficient if you run the report with filtered values.