MySQL trying to get hourly summary and count on row data - mysql

MyTable is:
tday char(3)
dow int(1)
tdate date
ttime time
T0 decimal(5,2)
T1 decimal(5,2)
T2 decimal(5,2)
T3 decimal(5,2)
Total decimal(8,2)
Given the above structure and following data:
DoW IM CDate CTime G0 G1 G2 G3
Thu 4 2010-12-02 05:29:15 1 3 0 11
Thu 4 2010-12-02 05:34:22 0 4 1 0
Thu 4 2010-12-02 05:39:28 6 0 7 0
Thu 4 2010-12-02 05:44:35 8 7 3 9
Thu 4 2010-12-02 05:49:41 0 7 0 8
Thu 4 2010-12-02 05:54:48 1 7 0 1
Thu 4 2010-12-02 05:59:54 3 0 5 3
Thu 4 2010-12-02 06:05:01 0 9 1 0
Thu 4 2010-12-02 06:10:07 2 9 10 0
Thu 4 2010-12-02 06:15:13 0 0 16 0
Thu 4 2010-12-02 06:20:20 2 0 8 0
Thu 4 2010-12-02 06:25:26 1 0 0 0
Thu 4 2010-12-02 06:30:33 1 5 19 21
Thu 4 2010-12-02 06:35:39 3 0 6 0
Thu 4 2010-12-02 06:40:46 3 4 7 2
Thu 4 2010-12-02 06:45:52 3 3 0 20
Thu 4 2010-12-02 06:50:58 5 0 7 10
Thu 4 2010-12-02 06:56:05 0 7 7 0
Thu 4 2010-12-02 07:01:11 7 0 10 3
Thu 4 2010-12-02 07:06:18 0 0 0 1
Thu 4 2010-12-02 07:11:24 0 0 0 0
Thu 4 2010-12-02 07:16:31 9 3 1 0
Thu 4 2010-12-02 07:21:37 0 0 3 10
Thu 4 2010-12-02 07:26:44 0 1 3 0
What I am trying to get is the sum of columns G0..G3 by the Hour per Day.
I have tried "Select CTime, sum(G0), sum(G1), sum(G2), sum(G3) from MyTable group by CTime order by CDate;" and various like statements without getting any success. The results I am trying to get is as follows:
DoW IM CDate CTime G0 G1 G2 G3
Thu 4 2010-12-02 05:00:00 19 28 16 32
Thu 4 2010-12-02 06:00:00 20 51 86 65
Thu 4 2010-12-02 07:00:00 16 4 17 14
Could you kindly assist. I have spent considerable time looking at already submitted solutions and other answers on the web but nothing comes close to what I think I need in the particular SQL statement required.
Thanks. Grahame

I think you're looking for something like
SELECT DoW, IM, CDate, HOUR(CTime) AS recorded_hour, SUM(G0) AS sum_0,
SUM(G1) AS sum)1, SUM(G2) AS sum_2, SUM(G3) AS sum_3
FROM MyTable
GROUP BY recorded_hour
If you want to have the hour for different dates to be distinct, then you just have to add the date column to the group by clause

What type of CTime and CDate is?
Could your past here normal table structure in pre&code
Try to run this:
Select CDate, HOUR(CTime), sum(G0), sum(G1), sum(G2), sum(G3) from MyTable group by CDate, HOUR(CTime) order by CDate, CTime
HOUR function

Related

What kind of changes do I need to this so I can auto sort two columns in Google sheets (date columns)?

I have two columns - column 4 is a date, column 5 is a time field (HH:MM). I would like it to auto sort by both (ascending).
The code below works if both columns are numbers but doesn't work when I do data validation and convert column 4 into a date field and 5 into time (HH:MM).
I'm not adamant on using a modification of the script below, couldn't think of a clean formula that would get the job done (using one sheet).
var SORT_COLUMN_INDEX = 4;
var SORT_COLUMN_SECOND = 5;
var ASCENDING = true;
var NUMBER_OF_HEADER_ROWS = 1;
var activeSheet;
function autoSort(sheet) {
var range = sheet.getDataRange();
if (NUMBER_OF_HEADER_ROWS > 0) {
range = range.offset(NUMBER_OF_HEADER_ROWS, 0);
}
// Perform the actual sort.
range.sort( {
column: SORT_COLUMN_SECOND,
ascending: ASCENDING
});
range.sort( {
column: SORT_COLUMN_INDEX,
ascending: ASCENDING
} );
}
function onEdit(event) {
var editedCell;
activeSheet = SpreadsheetApp.getActiveSheet();
editedCell = activeSheet.getActiveCell();
if (editedCell.getColumn() == SORT_COLUMN_INDEX) {
autoSort(activeSheet);
}
}
function onOpen(event) {
activeSheet = SpreadsheetApp.getActiveSheet();
autoSort(activeSheet);
}
function onInstall(event) {
onOpen(event);
}
This function combines COL3 and COL4 using the column 3 as the day and column 4 as the hour and replaces column 3 with a datetime. It also deletes column 4 and writes the data back into the spreadsheet and sorts on column 3 which is now a datetime.
function myfunc() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1');
const [hA, ...rows]=sh.getDataRange().getValues();
let idx={};
hA.forEach((h,i)=>{idx[h]=i;});
let vA=rows.map((r,i)=>{
r[idx['COL3']]= Utilities.formatDate(new Date(2021,0,r[idx['COL3']-1],r[idx['COL4']]),Session.getScriptTimeZone(),"E MMM dd, yyyy HH:mm:ss");
return [r[idx['COL1']],r[idx['COL2']],r[idx['COL3']],r[idx['COL5']],r[idx['COL6']],r[idx['COL7']],r[idx['COL8']],r[idx['COL9']],r[idx['COL10']]];
});
hA.splice(3,1);
sh.clearContents();
sh.getRange(1,1,1,hA.length).setValues([hA]);
sh.getRange(2,1,vA.length,vA[0].length).setValues(vA);
sh.getRange(2,1,sh.getLastRow()-1,sh.getLastRow()).sort({column:3,ascending:true});;
}
Starting Data with random numbers:
COL1
COL2
COL3
COL4
COL5
COL6
COL7
COL8
COL9
COL10
8
14
18
9
5
16
18
13
4
3
5
6
12
6
4
10
15
14
15
11
0
9
3
12
9
14
17
6
8
5
16
15
17
17
12
9
14
15
5
16
3
6
15
6
0
9
15
8
0
8
13
8
13
8
15
0
4
1
16
13
2
10
11
3
14
14
1
19
5
1
12
5
3
14
5
2
5
7
8
3
12
4
6
9
8
15
15
16
4
18
3
18
15
15
7
3
15
18
5
2
11
5
3
6
13
15
15
18
9
14
2
10
4
4
8
16
13
8
0
11
0
7
3
10
9
2
6
11
11
11
17
9
17
10
11
4
5
1
12
19
11
8
19
10
7
2
5
4
1
6
8
3
7
4
17
3
11
1
19
13
9
17
16
15
17
4
16
13
15
10
7
13
1
15
8
17
6
4
6
12
11
10
5
19
10
6
8
12
17
12
16
18
2
0
4
11
3
19
2
8
And then after running the function:
COL1
COL2
COL3
COL5
COL6
COL7
COL8
COL9
COL10
8
3
Sun Jan 03 2021 04:00:00 GMT-0700 (Mountain Standard Time)
17
3
11
1
19
13
12
4
Mon Jan 04 2021 09:00:00 GMT-0700 (Mountain Standard Time)
8
15
15
16
4
18
11
5
Tue Jan 05 2021 06:00:00 GMT-0700 (Mountain Standard Time)
13
15
15
18
9
14
12
5
Tue Jan 05 2021 14:00:00 GMT-0700 (Mountain Standard Time)
5
2
5
7
8
3
5
6
Wed Jan 06 2021 06:00:00 GMT-0700 (Mountain Standard Time)
4
10
15
14
15
11
3
6
Wed Jan 06 2021 06:00:00 GMT-0700 (Mountain Standard Time)
0
9
15
8
0
8
0
7
Thu Jan 07 2021 10:00:00 GMT-0700 (Mountain Standard Time)
9
2
6
11
11
11
13
8
Fri Jan 08 2021 08:00:00 GMT-0700 (Mountain Standard Time)
15
0
4
1
16
13
11
8
Fri Jan 08 2021 10:00:00 GMT-0700 (Mountain Standard Time)
7
2
5
4
1
6
17
9
Sat Jan 09 2021 10:00:00 GMT-0700 (Mountain Standard Time)
11
4
5
1
12
19
0
9
Sat Jan 09 2021 12:00:00 GMT-0700 (Mountain Standard Time)
9
14
17
6
8
5
2
10
Sun Jan 10 2021 03:00:00 GMT-0700 (Mountain Standard Time)
14
14
1
19
5
1
2
10
Sun Jan 10 2021 04:00:00 GMT-0700 (Mountain Standard Time)
8
16
13
8
0
11
11
10
Sun Jan 10 2021 19:00:00 GMT-0700 (Mountain Standard Time)
10
6
8
12
17
12
7
13
Wed Jan 13 2021 15:00:00 GMT-0700 (Mountain Standard Time)
8
17
6
4
6
12
8
14
Thu Jan 14 2021 09:00:00 GMT-0700 (Mountain Standard Time)
5
16
18
13
4
3
16
15
Fri Jan 15 2021 17:00:00 GMT-0700 (Mountain Standard Time)
12
9
14
15
5
16
9
17
Sun Jan 17 2021 15:00:00 GMT-0700 (Mountain Standard Time)
17
4
16
13
15
10
16
18
Mon Jan 18 2021 00:00:00 GMT-0700 (Mountain Standard Time)
4
11
3
19
2
8
3
18
Mon Jan 18 2021 15:00:00 GMT-0700 (Mountain Standard Time)
7
3
15
18
5
2

Compute Multiple Average Commands Simultaneously

This is a follow-up to a similar post...
I have the following dataset that looks like this. I'd like to select only those who have a "1" for the ESITwoToFive variable and then compute the AVG total_ED_LOS for each unique date. I'd also like to do the same for the ESIFourFive variable.
ID CheckinDate ESITwoToFive ESIFourFive Total_ED_Los
1 Feb 7 1 0 23
2 Feb 7 0 1 23
3 Feb 7 1 0 28
4 Feb 8 1 0 43
5 Feb 8 1 0 83
6 Feb 8 0 1 29
7 Feb 8 0 1 32
8 Feb 9 1 0 93
9 Feb 9 1 0 77
10 Feb 9 0 1 33
I was kindly given the following code to use to compute for the ESITwoToFive variable, which works.
select t.checkin_date, avg(t.total_ed_los) as [Avg LOS]
from [Fast Track Quality Research ESI Levels] t
where t.esitwotofive = 1
group by t.checkin_date
Desired output:
Checkindate Avg LOS for ESITwoToFive Avg LOS for ESIFourFive
Feb 7 24 23
Feb 8 54 30
Feb 9 86 56
The conditional is likely to be the cleanest solution, but just to offer an alternative without conditionals:
select
t.checkin_date,
sum(t.total_ed_los * t.esitwotofive) / sum(t.esitwotofive),
sum(t.total_ed_los * t.esifourfive) / sum(t.esifourfive),
from
[Fast Track Quality Research ESI Levels] t
group by
t.checkin_date
Try using IIf() conditional expression:
SELECT t.checkin_date, Avg(IIf(ESITwoToFive=1,t.total_ed_los,Null)) AS [AvgLOStwo],
Avg(IIf(ESIFourFive=1,t.total_ed_los,Null)) as [AvgLOSfour]
FROM [Fast Track Quality Research ESI Levels] t
GROUP BY t.checkin_date

Mysql find common values for all users

We are developing an local shop reccomendation system and in one of our sql queries we had a problem
We want to fetch the companies which all users in same cluster rated , but if any one of the users in the same group doesnt rated the company we wouldnt want to fetch it
SELECT ml_user_clusters.primaryUser,ml_user_clusters.clusterId,ml_ratings.companyId,ml_ratings.rating,ml_user_labels.groupId FROM ml_user_clusters
LEFT JOIN ml_ratings ON ml_ratings.userId = ml_user_clusters.primaryUser
LEFT JOIN ml_company_user_labels ON ml_company_user_labels.companyId = ml_ratings.companyId
LEFT JOIN ml_user_labels ON ml_user_labels.groupId = ml_company_user_labels.labelId
WHERE ml_user_clusters.clusterId = 0
We've started to add a query like in the below but couldnt able to finish it with proper AND clause
And our data is like in the below: So in the result we would like to have only the companies which has groupId=6 because all users in the same cluster(clusterId=0) rated a company with groupId = 6
primaryUser clusterId companyId rating groupId
497 0 135 5 NULL
498 0 135 10 NULL
79 0 135 12 NULL
501 0 135 10 NULL
79 0 85 14 2
79 0 8 4 5
79 0 98 11 5
79 0 3 5 5
497 0 6 7 6
500 0 6 7 6
499 0 29 7 6
497 0 29 7 6
499 0 77 7 6
500 0 29 7 6
498 0 6 7 6
500 0 77 11 6
500 0 130 3 6
498 0 130 3 6
501 0 77 19 6
499 0 6 7 6
79 0 30 1 7
500 0 30 7 7
79 0 48 7 9
79 0 39 1 13
79 0 48 7 13
499 0 6 7 15
497 0 6 7 15
79 0 8 4 15
500 0 6 7 15
79 0 98 11 15
498 0 6 7 15
79 0 3 5 15
79 0 81 7 15
79 0 3 5 17
79 0 82 7 17
79 0 103 7 17
79 0 118 3 17
79 0 63 3 17
501 0 118 7 17
79 0 82 7 19
79 0 118 3 19
79 0 63 3 19
501 0 118 7 19
79 0 39 1 21
79 0 85 14 23
Expected output must be: (Because all unique users in Cluster=0 has rated a company which has GroupID=6 )
primaryUser clusterId companyId rating groupId
497 0 6 7 6
500 0 6 7 6
499 0 29 7 6
497 0 29 7 6
499 0 77 7 6
500 0 29 7 6
498 0 6 7 6
500 0 77 11 6
500 0 130 3 6
498 0 130 3 6
501 0 77 19 6
499 0 6 7 6
Do you have any idea how we can fix that problem?
Something like this should work,you should build a fiddle for better testing.
Explanation: you count distinct users grouped by group id and compare with the total number of distinct users.If the two match it means all users in that respective groupid have voted.
SELECT ml_user_labels.groupId
FROM ml_user_clusters
LEFT JOIN ml_ratings ON ml_ratings.userId = ml_user_clusters.primaryUser
LEFT JOIN ml_company_user_labels ON ml_company_user_labels.companyId = ml_ratings.companyId
LEFT JOIN ml_user_labels ON ml_user_labels.groupId = ml_company_user_labels.labelId
WHERE ml_user_clusters.clusterId = 0
GROUP BY ml_user_labels.groupId
HAVING COUNT(DISTINCT ml_user_clusters.primaryUser) =
(SELECT COUNT(DISTINCT ml_user_clusters.primaryUser)
FROM ml_user_clusters
LEFT JOIN ml_ratings ON ml_ratings.userId = ml_user_clusters.primaryUser
LEFT JOIN ml_company_user_labels ON ml_company_user_labels.companyId = ml_ratings.companyId
LEFT JOIN ml_user_labels ON ml_user_labels.groupId = ml_company_user_labels.labelId
WHERE ml_user_clusters.clusterId = 0)x

Fill zero for missing month

I'm trying to display zero on missing month, but didn't succeed.
Table:
clicks | impressions | ctr | position | month | year
111 2709 4 20 3 2015
101 2695 3 20 6 2015
76 2714 2 21 7 2015
.
.
.
64 1212 4 25 11 2015
81 1905 4 24 12 2015
Required output:
clicks | impressions | ctr | position | month | year
0 0 0 0 1 2015
0 0 0 0 2 2015
111 2709 4 20 3 2015
0 0 0 0 4 2015
0 0 0 0 5 2015
101 2695 3 20 6 2015
.
.
.
64 1212 4 25 11 2015
81 1905 4 24 12 2015
Like #jarlh suggested ,you can do it like this: creating a 'table' that contains all month availabe(you will have to populate it your self, add which month and years you want) and then left join to the original table and when value not exists, put 0.
select coalese(s.clicks,0) as clicks,
coalese(s.impressions ,0) as impressions,
coalese(s.ctr ,0) as ctr ,
coalese(s.position ,0) as position ,
t.month,
t.year
from(
SELECT 1 as month_num,2015 as year_num
union SELECT 2,2015
union select 3,2015
union select 4,2015 ....) t
LEFT OUTER JOIN YourTable s
ON(t.month_num = s.month and t.year_num = s.year)

access filter needed

Here is a sample data set
-----------------------------------------------------------------------------------------
id nameid name score diff include quantity grade
---------------------------------------------------------------------------------------
7 0002 MO 10 0 0 25 3
8 0002 MO 18 0 1 25 3
9 0002 MO 20 0 0 25 3
10 0002 MO 14 0 0 17 6
11 0002 MO 100 0 0 17 6
11 0002 MO 100 0 0 17 6
12 0003 MA 10 0 0 12 3
13 0003 MA 18 0 0 12 3
14 0003 MA 20 0 0 12 3
15 0003 MA 14 0 0 25 6
16 0003 MA 100 0 1 25 6
17 0003 MA 100 0 0 25 6
12 0004 MB 10 0 0 12 3
13 0004 MB 18 0 1 12 3
14 0004 MB 20 0 0 12 3
15 0004 MB 14 0 0 07 6
16 0004 MB 100 0 1 07 6
17 0004 MB 100 0 0 07 6
I have a query that returns the above table.
Note that in each group of six, there WILL be atleast one row that has value 1 in include column.
Look at ref: access query needed but not needed.
Also for each group of six, there are three rows that has grade = 3 and 3 rows that has grade = 6.
And corresspondingly, the grade 3 and grade 6 have the same quantity in that group.
What I want to do is filter out all the rows that have less then 15 quantity.
However, I still want to group them by 6.
I want to remove a "group" that has both quantity < 15 for both grade 3 and 6. From the above data set
I wwant the following result:
-----------------------------------------------------------------------------------------
id nameid name score diff include quantity grade
---------------------------------------------------------------------------------------
7 0002 MO 10 0 0 25 3
8 0002 MO 18 0 1 25 3
9 0002 MO 20 0 0 25 3
10 0002 MO 14 0 0 17 6
11 0002 MO 100 0 0 17 6
11 0002 MO 100 0 0 17 6
12 0003 MA 10 0 0 12 3
13 0003 MA 18 0 0 12 3
14 0003 MA 20 0 0 12 3
15 0003 MA 14 0 0 25 6
16 0003 MA 100 0 1 25 6
17 0003 MA 100 0 0 25 6
So basically if a group of six has include = 1 in any row, and either grade 3 or 6 quantity > 15 then I want the entire group.
"So basically if a group of six has include = 1 in any row, and either grade 3 or 6 quantity > 15 then I want the entire group."
My guess is this query will identify the candidate nameid groups:
SELECT DISTINCT nameid
FROM YourTable
WHERE
include = 1
AND quantity > 15
AND (grade = 3 OR grade = 6);
If I guessed correctly, you can save it as a separate query, or use it as a subquery, and INNER JOIN it to YourTable to limit the rows returned to only those where nameid meets your criteria. It might look close to this untested SELECT statement:
SELECT y.id, y.nameid, y.[name], y.score, y.diff, y.include, y.quantity, y.grade
FROM
YourTable AS y
INNER JOIN [
SELECT DISTINCT nameid
FROM YourTable
WHERE
include = 1
AND quantity > 15
AND (grade = 3 OR grade = 6)
]. AS q
ON y.nameid = q.nameid
ORDER BY y.nameid;
Edit: Add an index on nameid if you don't already have one.