Average date of visiting website - mysql

I'd like to know the average dates per week that users have been visited the website 'A'. If the user hasn't visited the website 'A', I exclude the data (e.g., id = 2). And I also need to consider the date range (limit it to a week range, e.g., 01-JAN-2018 to 07-JAN-2018)
Sample input (Table:User)
id date website
1 01-JAN-2018 A
1 03-JAN-2018 B
1 04-JAN-2018 C
1 04-JAN-2018 C
2 03-JAN-2018 C
3 03-JAN-2018 A
3 05-JAN-2018 B
4 05-JAN-2018 A
The first step will like this:
id date website
1 01-JAN-2018 A
1 03-JAN-2018 B
1 04-JAN-2018 C
1 04-JAN-2018 C
3 03-JAN-2018 A
3 05-JAN-2018 B
4 05-JAN-2018 A
The output will only return the average dates that users visiting websites (including ABC). In this case, user 1 visited three days a week (ignore duplicates) and user 3 visited two days a week. The average dates of hits will be sum(days)/number of users.
My first thought:
SELECT COUNT(Date), Date
FROM user
WHERE id IN (
SELECT id FROM user
WHERE web = 'A'
);
Assume that I only want to consider this week range (01-JAN-2018 to 07-JAN-2018). I want to figure out the average of dates of visiting in one week. Any thoughts for this? Thanks!
Link for Demo

If you want to group by hits in a week, you might try something more like this:
select year(STR_TO_DATE(date,'%d-%b-%y')) year,
weekofyear(STR_TO_DATE(date,'%d-%b-%y')) week,
count(*) hits
from user
group by year(STR_TO_DATE(date,'%d-%b-%y')), weekofyear(STR_TO_DATE(date,'%d-%b-%y'))
The group by is the key: this will group all the hits for a particular week together, whereas group by date will keep each day separate.
If you want an average for multiple weeks, you would need to use this query as a subquery, and do an average on the count column.
And as was stated in comments, this would be a LOT easier (not to mention more efficient) if the date was stored as a date and not as a varchar

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

SQL count based on timediff and column containing a string

I'm using SQL Workbench.
cust_num date notes
1234 2016-02-01 advice
1234 2016-02-01 something else
1234 2016-02-02 order
1234 2016-02-03 order
4421 2016-02-15 advice
4421 2016-02-17 order
4421 2016-02-18 something else
4421 2016-02-24 order
I know the above is a bit unclear, but basically, there's 3 columns in the above table. One showing customer_num (customer number), one showing date and one showing a notes field.
From the above, I want to perform two queries. I am newish to this so, I hope this is clear. I'm using SQL workbench.
i) I want to count the number of DISTINCT 'customer_num's that placed an order within 4 days of receiving advice.
So the answer based on the table above would be 3. This is because cust_num '1234' made two orders within 4 days and cust_num '4421' made 1 order. So that totals 3
ii)I want to count the number of DISTINCT customer_num's that placed an order within 15 days of receiving advice. Only stipulation is that I don't want to re-count those from (i) that placed an order within 4 days. I want to exclude them.
So the answer to this would be 1. Customer_num '4421' placed 1 order that was bigger than 4 days but smaller than or including 15 days.
Any help really appreciated. Thank you.
One method is to use exists:
select count(distinct cust_num)
from customers t
where exists (select 1
from customers t2
where t2.cust_num = t.cust_num and
t2.date between t.date and date_add(t.date, interval 3 day)
);
The two queries have the same structure. You just need to change the condition in the where clause in the subquery.

Count the number of rows that have a specific piece of data?

I have the following table
id Desc User
1 Print 14
2 Print 7
3 Copy 14
4 Print 19
5 Copy 7
6 Copy 19
7 Attach 19
What I'm trying to do is make a column that tells the number of rows per user.
Like this
id User Count
1 14 2
2 7 2
4 19 3
The Point of the report is to show how many activities each user has done.
I need to group by user and get the number of rows within each user.
The problem is, I'm not exactly sure how to do that, is it a unique statement somewhere?
Here's my query so far.
Select id
,User
From Table
Group By User
I am unsure how to implement the count though.
You should be able to get your result with the COUNT function:
SELECT
MIN(id),
User,
COUNT(User) AS Count
FROM
`table`
GROUP BY
User
Because you can get only one id value per User I assumed from your data that you want the minimum one.

MS Access: Using Single form to enter query parameters in MS access

compliment of the day.
Based on the previous feedback received,
After creating a Ticket sales database in MS Access. I want to use a single form to Query the price of a particular ticket at a particular month and have the price displayed back in the form in a text field or label.
Below are sample tables and used query
CompanyTable
CompID CompName
A Ann
B Bahn
C Can
KK Seven
- --
TicketTable
TicketCode TicketDes
10 Two people
11 Monthly
12 Weekend
14 Daily
TicketPriceTable
ID TicketCode Price ValidFrom
1 10 $35.50 8/1/2010
2 10 $38.50 8/1/2011
3 11 $20.50 8/1/2010
4 11 $25.00 11/1/2011
5 12 $50.50 12/1/2010
6 12 $60.50 1/1/2011
7 14 $15.50 2/1/2010
8 14 $19.00 3/1/2011
9 10 $40.50 4/1/2012
Used query:
SELECT TicketPriceTable.Price
FROM TicketPriceTable
WHERE (((TicketPriceTable.ValidFrom)=[DATE01]) AND ((TicketPriceTable.TicketCode)=[TCODE01]));
In MS Access, a mini boxes pops up to enter the parameters when running the query. How can I use a single form to enter the parameters for [DATE01] and [TCODE01]. and the price displayed in the same form in a textfield (For further calculations).
Such as 'Month' field equals to input to [DATE01] parameter
'Ticket Code' equals to input for [TCODE01] parameter
Textfield equals to output of the query result (Ticket price)
If possible, I would like to use only the Month and Year in this format MM/YYYY.The day is not necessarry. How can I achieve it in MS Access?
If any question, please don't hesitate to ask
Thanks very much for your time and anticipated feedback.
You can refer to the values in the form fields by using expressions like: [Forms]![NameOfTheForm]![NameOfTheField]
Entering up to 300 different types of tickets
Answer to your comment referring to Accessing data from a ticket database, based on months in MS Access)
You can use Cartesian products to create a lot of records. If you select two tables in a query but do not join them, the result is a Cartesian product, which means that every record from one table is combined with every record from the other.
Let's add a new table called MonthTable
MonthNr MonthName
1 January
2 February
3 March
... ...
Now if you combine this table containing 12 records with your TicketTable containing 4 records, you will get a result containing 48 records
SELECT M.MonthNr, M.MonthName, T.TicketCode, T.TicketDes
FROM MonthTable M, TicketTable T
ORDER BY M.MonthNr, T.TicketCode
You get something like this
MonthNr MonthName TicketCode TicketDes
1 January 10 Two people
1 January 11 Monthly
1 January 12 Weekend
1 January 14 Daily
2 February 10 Two people
2 February 11 Monthly
2 February 12 Weekend
2 February 14 Daily
3 March 10 Two people
3 March 11 Monthly
3 March 12 Weekend
3 March 14 Daily
... ... ... ...
You can also get the price actually valid for a ticket type like this
SELECT TicketCode, Price, ActualPeriod AS ValidFrom
FROM (SELECT TicketCode, MAX(ValidFrom) AS ActualPeriod
FROM TicketPriceTable
WHERE ValidFrom <= Date
GROUP BY TicketCode) X
INNER JOIN TicketPriceTable T
ON X.TicketCode = T.TicketCode AND X.ActualPeriod=T.ValidFrom
The WHERE ValidFrom <= Date is in case that you entered future prices.
Here the subquery selects the actually valid period, i.e. the ValidFrom that applies for each TicketCode. If you find sub-selects a bit confusing, you can also store them as query in Access or as view in MySQL and base a subsequent query on them. This has the advantage that you can create them in the query designer.
Consider not creating all your 300 records physically, but just getting them dynamically from a Cartesian product.
I let you put all the pieces together now.
In Access Forms you can set the RecordSource to be a query, not only a table. This can be either the name of a stored query or a SQL statement. This allows you to have controls bound to different tables through this query.
You can also place subforms on the main form that are bound to other tables than the main form.
You can also display the result of an expression in a TextBox by setting the ControlSource to an expression by starting with an equal sign
=DLookUp("Price", "TicketPriceTable", "TicketCode=" & Me!cboTicketCode.Value)
You can set the Format of a TextBox to MM\/yyyy or use the format function
s = Format$(Now, "MM\/yyyy")

MySQL GROUP BY with multiple parameters hiding zeros

I've read similar questions here on stackoverflow, but the OP's table structure is never quite the same as mine, so the answer doesn't work for me. The posts I've read are only trying to GROUP BY one column as opposed to two. I'm using MySQL, latest stable release.
Here's my table "reference":
id formatID referenceTime
1 1 2011-6-12 12:40
2 2 2011-6-12 1:04
3 4 2011-6-12 1:03
4 2 2011-6-12 15:20
5 3 2011-6-12 9:30
6 3 2011-6-12 2:55
7 5 2011-6-12 13:15
8 1 2011-6-12 12:32
(etc)
I want to create a query that show how many of each type of format occurred by hour of day. The point of this is to see what is the busiest time of day. I am trying to write a query that will create output that I can use for some simple graph web apps (Highcharts.js). I want it to look like this:
Timeofday Subgroup Count
12AM 1 2
12AM 2 6
12AM 3 7
12AM 4 2
12AM 5 0
1AM 1 3
1AM 2 3
1AM 3 0
1AM 4 0
1AM 5 1
(etc)
I'm using this query:
SELECT date_format(referenceTime,'%I %p') AS timeofday,
reference.referenceFormatID AS subgroup,
count(*) AS count
FROM reference
GROUP BY timeofday,subgroup ASC
However, the output skips "rows" where the count equals zero and so ends up looking like this:
Timeofday Subgroup Count
12AM 1 2
12AM 2 6
1AM 3 7
1AM 4 2
1AM 5 1
3AM 1 3
6AM 2 3
7AM 3 1
7AM 4 1
9AM 5 1
(etc)
I need those zeros to be able to create a properly formatted data series for my app.
The LEFT JOIN method where you put all the times into a second table isn't working for me because I am grouping by two different columns. Apparently, the LEFT JOIN criteria is satisfied as long as each hour shows up somewhere in the output table, but I need each hour to appear for each format.
Any suggestions?
You have two options, either create a lookup table with the possible hours in it, or use strange query involving the dual table and union to get the values that you are looking for.
In the first case, you would have a table with maybe a single field for the moment, let's just call it hours and the field is timeofday.
In the hours timeofday, you would have the following data:
timeofday
12AM
1AM
2AM
....
Then your query is as simple as
SELECT hours.timeofday,
reference.referenceFormatID AS subgroup,
count(reference.referenceFormatID) AS count
FROM hours
LEFT JOIN reference on date_format(referenceTime,'%I %p') = hours.timeofday
GROUP BY hours.timeofday,subgroup ASC
EDIT
To get all combinations, you would also need a formats table with all the possible formatIDs as was mentioned by rfausak. You could also do this with a distinct, but let's just assume that you have this table, let's call it formats. Again, this table could have a single column.
Part 1 is to get all the combinations:
SELECT hours.timeofday,
formats.ID
from hours
join formats
This is a Cartesian join that would merge all possible hours and format IDs.
Now we add in the LEFT JOIN
SELECT hours.timeofday,
formats.ID,
count(reference.subgroup)
FROM hours
JOIN formats
LEFT JOIN reference on date_format(referenceTime,'%I %p') = hours.timeofday
AND reference.subgroup = formats.ID
GROUP BY hours.timeofday,formats.ID ASC
If you try to do it using a DUAL table look up, you can use a method similar to generate days from date range