I have a table containing the following columns:
stats_date (YYYY-MM-DD)
registered (INT)
opened_form (INT)
Compose a query that will return the total registered, and opened_form by month for the last 3 months. Also a calculated column called conversion_rate which is the registered column divided by the opened_form.
Are you just looking for aggregation? Date/time functions differ significantly among databases, but the idea is:
select year(stats_date), month(stats_date),
sum(registered), sum(opened_form),
sum(registered) * 1.0 / sum(opened_form) as ratio
from t
group by year(stats_date), month(stats_date)
order by min(stats_date);
Of course, your database might have a different way of extracting the year and month from a date.
You can see the ANSI SQL at page 187 to understand how agregation works. To know how to group your column by Month you need to check the documentation of your db, usually is MONTH(COLUMN_NAME).
Related
Im trying to calculate the average time a tool stays on loan. The time a tool stays on loan is the number of days between loan_status_change_date and tool_out_date (table columns). the date type of these 2 columns is ex: 01-SEP-17
whats the best way to approach this?
We can do arithmetic with Oracle dates. It's not clear from the column names which one is the start of the loan and which the end; in the following example I've assumed loan_status_change is when the tool is returned.
select tool
, avg(loan_status_change - tool_out_date) as avg_loan_days
from your_table
group by tool
/
The AVG() function is an aggregate function, so it handles the /ns for us. The substraction is to calculate the length of a particular loan, which is the value you want to average. The result of that substraction already is a number of days, so no further transformation is necessary. If your columns have a time element then the result might not be an integer.
I need to a value associated to a month and a user in a table. And I want to perform queries on it. I don't know if there is a column data type for this type of need. If not, should I:
Create a string field and build year-month concatenation (2017-01)
Create a int field and build year-month concatenation (201701)
Create two columns (one year and one month)
Create a date column at the beginning of the month (2017-01-01 00:00:00)
Something else?
The objective is to run queries like (pseudo-SQL):
SELECT val FROM t WHERE year_month = THIS_YEAR_MONTH and user_id='adc1-23...';
I would suggest not thinking too hard about the problem and just using the first date/time of the month. Postgres has plenty of date-specific functions -- from date_trunc() to age() to + interval -- to support dates.
You can readily convert them to the format you want, get the difference between two values, and so on.
If you phrase your query as:
where year_month = date_trunc('month', now()) and user_id = 'adc1-23...'
Then it can readily take advantage of an index on (user_id, year_month) or (year_month, user_id).
If you are interested in display values in YYYY-MM formt you can use to_char(your_datatime_colum,'YYYY-MM')
example:
SELECT to_char(now(),'YYYY-MM') as year_month
I have a table named Sales and a column within it named Date. I'm simply trying to find how many sales were made on a specific date. My intuition was to use something like this:
SELECT COUNT(Date) FROM Sales WHERE Date='2015-04-04'
this should count all sales that were made on that date, but that returns 0. What am I doing wrong?
While it is difficult to be precise without table definitions or an indication of what RDBMS you are using, it is likely that Date is a time/date stamp, and that the result you want would be obtained either by looking for a range from the beginning of the day to the end of the day in your WHERE clause, or by truncating Date down to a date without the time before comparing it to a date.
Try the below once.
select count(*) from <t.n> where date like '2015-04-04%';
When you want to find the count of rows based on a field (Date) You need to Group By over it like this:
SELECT Date, COUNT(*)
FROM Sales
GROUP BY Date
Now you have all count of rows for each Date.
Type and Value of Date is important in the result of the above query.
For example in SQL Server your best try is to convert a DateTime field to varchar and then check it as the result of CONVERT like this:
SELECT COUNT(*)
FROM Sales
WHERE CONVERT(VARCHAR, Date, 111) = '2015/04/04'
How does Min function work on dates ? If 2 records have the same date and time stamp , the min function returns 1. Does it pull records based on when it was put into the table ?
MIN is an aggregate function so it will return 1 record in your question's case. Since the two records have the same date and timestamp it doesn't matter which date and timestamp are returned (they're the same). Finally, the time the records were inserted is not considered.
MIN() returns the smallest of all selected values of a column. It seems to me that your statement may simply be asking if a minimum exists.
Please post your sql statement.
possibly this is what you need:
SELECT MIN (date) AS "Min Date"
FROM tablename;
Elliot already expained it.
Just a sidenode, if you are using MySQL: MySQL allows to aggregate on a certain column, while fetching other columns without aggregation. (SQL Server does NOT allow that!)
Example:
date | name
2015-03-06 | A
2015-03-06 | B
Using SELECT Min(date), name FROM table on MySQL will return various results.
Sometimes it will be
2015-03-06 | A
sometimes
2015-03-06 | B
Docu:
When using this feature, all rows in each group should have the same
values for the columns that are omitted from the GROUP BY part. The
server is free to return any value from the group, so the results are
indeterminate unless all values are the same.
SQL Server will throw an error, that no aggregation has been performed on column name. See also http://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
MySQL works this way, cause sometimes grouping on the second column is not really required, for example:
SELECT MAX(id), user_id FROM posts WHERE user_id = 6
(There could be NO other user_id than 6, so aggregation is not required in MySQL - However not paying attention on THIS will lead to wrong results as example one shows.)
I've got a table with purchase orders stored in it. Each row has a timestamp indicating when the order was placed. I'd like to be able to create a report indicating the number of purchases each day, month, or year. I figured I would do a simple SELECT COUNT(xxx) FROM tbl_orders GROUP BY tbl_orders.purchase_time and get the value, but it turns out I can't GROUP BY a timestamp column.
Is there another way to accomplish this? I'd ideally like a flexible solution so I could use whatever timeframe I needed (hourly, monthly, weekly, etc.) Thanks for any suggestions you can give!
This does the trick without the date_trunc function (easier to read).
// 2014
select created_on::DATE from users group by created_on::DATE
// updated September 2018 (thanks to #wegry)
select created_on::DATE as co from users group by co
What we're doing here is casting the original value into a DATE rendering the time data in this value inconsequential.
Grouping by a timestamp column works fine for me here, keeping in mind that even a 1-microsecond difference will prevent two rows from being grouped together.
To group by larger time periods, group by an expression on the timestamp column that returns an appropriately truncated value. date_trunc can be useful here, as can to_char.