I have a table with the fields: resourceID,work_date,stringValue
I'm trying to build an Access query that will show a count of how many different resourceID numbers with a given stringValue occur in each week over a given date range. Using partition() seems to be the simplest approach, however, when I use the following query:
select partition([work_date],#6/6/2011#,#9/4/2011#,7),stringValue,
count(resourceID) from
(select distinct resourceID,work_date,stringValue from myTable) as subQuery
group by partition([work_date],#6/6/2011#,#9/4/2011#,7), stringValue
then I have two problems:
-My dates end up formatted as integers, e.g.:
:40699
40700:40706
40784:40790
whereas I want them to appear as, e.g., 6/6/2011:6/12/2011 (I also don't want the :40699 value)
-resourceID gets counted more than once per week if it appears on more than one weekday; I just want it to be counted once for each stringValue if it appears at all that week. I thought the distinct qualifier would accomplish this but it didn't.
EDIT: I've solved the excess resourceID count by putting the partition in a subquery as follows:
select datePartition,stringValue,count(ID)
from (select partition() as datePartition, stringValue, ID
from (select distinct stringvalue,ID,work_date))
group by datePartition,stringvalue
and then pulling count(ID) from that subquery. Still can't figure out the date formatting, though.
I see 2 solutions, but I see no reason for using Partition() here !
Solution 1: use SELECT Format([DateFact];"ww-yyyy") as weekOfYear will return the week number and year: fine for grouping by week, displaying the week number.
Solution 2: use SELECT [DateFact]-Weekday([datefact]+1) as weekStarting will return first day of the week as a nicely formatted date: fine for grouping by week, displaying the week starting day.
To get rid of the range which ends with 40699, try revising the subquery piece. Add a WHERE condition to limit rows to work_date values >= #6/6/2011#
SELECT DISTINCT resourceID, work_date, stringValue
FROM myTable
WHERE work_date >= #6/6/2011#;
I'm not clear about your description regarding the duplicate rows from the SELECT DISTINCT. One possibility could be that at least some of your work_date values contain different time values from the same date. So two rows with the same resourceID and stringValue, but work_date values of #6/6/2011 01:00 AM# and #6/6/2011 02:00 AM#, would legitimately qualify as distinct.
If that's not the explanation, clarify your question by showing us a smallish set of data from myTable, and the resultset of that data which illustrates how you want the data evaluated.
AFAICT, the issue about Partition() presenting your date ranges as whole numbers is unavoidable. According to the help topic, Partition() expects whole numbers for its parameters. Apparently it's willing to accept your Date/Time values by casting them to whole numbers. But it's not willing/able to transform them back to date strings. You would have to transform them back yourself. A user-defined function could do it when called from a query.
Public Function WholeNumRange2Date(ByVal pRange As String)
Const cstrFmt As String = "m/d/yyyy"
Dim varPieces As Variant
varPieces = Split(pRange, ":")
WholeNumRange2Date = Format(CDate(varPieces(0)), cstrFmt) & _
":" & Format(CDate(varPieces(1)), cstrFmt)
End Function
An example from the Immediate Window which uses that function ...
? WholeNumRange2Date("40700:40706")
6/6/2011:6/12/2011
Related
My company uses a SQL Server database.
Is it possible to use a range of cells as a condition in a SQL query if it equals ANY of those values? Can it even use date ranges on the same rows?
Reference Example:
Data Example:
Output Desired:
Question 1:
Can I reference an entire column?
SELECT ID, sum(units) FROM sales WHERE ID = any ID in Column A
Question 2:
Can I specify just a cell range?
SELECT ID, sum(units) FROM table WHERE ID = any value in A2:A10
Question 3:
Can I add a date range cell reference with the possibility that the same ID may appear more than once but have a different date range (see 747375 in sample) and return results for both ranges separately?
SELECT ID, sum(units) FROM table WHERE ID = any value in A2:A10 AND DATE >= date found in column B that is next to ID in the same row AND DATE <= date found in column C that is next to ID in the same row
You can use between as following
select
r.id,
sum(units) as units
from reference r
join data d
on r.id = d.id
where d.date between r.start and r.end
group by
r.id
Question 1: Can I reference an entire column?
Yes. A default select without a where clause will reference the entire column.
Your example SELECT ID, sum(units) FROM sales WHERE ID = any ID in Column A is not logically sound. From the select, I am presuming that you want the sum of units for each individual ID, not the sum of all the units without regard to the ID. For this, you want to use group by
select ID, sum(units) totalunits
from sales
group by ID
There is no need for a where clause because you want everything.
Question 2: Can I specify just a cell range?
Yes.
And no.
There is no direct concept of "cell range" in SQL (well, maybe top but not really). Data is stored unordered in SQL. In Excel, the cell range "A2:A10" means "whatever values just happen to be in those cells at this point in time". Often this will mean "the 2nd through 10th values entered in time", or "the first through 9th values entered in time" if there is a header row. But then later you can sort the data differently and now there is different data there. In SQL, there is no order in storage. You can specify an order for the output when you select data, but that is manually specified for each select.
However, the related concept is probably rather obvious. "A2:A10" is often going to mean "the first 9 values by date/time", or "the largest/smallest 9 values" etc.
Your example SELECT ID, sum(units) FROM table WHERE ID = any value in A2:A10 needs to change to define what values you expect to be in A2:A10. For example, if A2:A10 represents the first 9 values by date, you would do something like this: (untested)
select ID, sum(units) totalunits
from sales
where ID in (select top(9) ID
from sales
order by date
)
group by ID
This would provide the sum of units for each of the IDs that were amongst the first 9 IDs entered by date (what to do with a tie for 9th I will not go into here).
Question 3: Can I add a date range cell reference with the possibility that the same ID may appear more than once but have a different date range (see 747375 in sample) and return results for both ranges separately?
This one is difficult to understand. And it might be meaningless based on the answer to your 2nd question. However, you can setup a query that chooses the IDs you want, and in that query you can also select the min and max dates. Finally, you can use the information from that query as a subquery to get the information by ID that has the sum of units within the min/max dates and one that is the sum of units outside the min/max dates. This would require some effort and I will not at this time try to figure that out for you.
Im trying to make a small report for myself to see how my much time I get inputed in my system every day.
The goal is to have my SQL to sum up the name, Total time worked and Total NG product found for one specific day.
In this order:
1.) Sort out my data for a specific 'date'. I.E 2016-06-03
2.) Present a DISTINCT value for 'operators'
3.) SUM() all time registered at this 'date' and by this 'operator' under 'total_working_time_h'
4.) SUM() all no_of_defects registered at this 'date' and by this 'operator' under 'no_of_defects'
date, operator, total_working_time_h, no_of_defects
Currently I get the data I want by using the Query below. But now I need both the DISTINCT value of the operator and the SUM of the information. Can I use sub-queries for this or should it be done by a loop? Any other hints where I can learn more about how to solve this?
If i run the DISTINCT function I don't get the opportunity to sum my data the way I try.
SELECT date, operator, total_working_time_h, no_of_defects FROM {$table_work_hours} WHERE date = '2016-06-03' "
Without knowing the table structure or contents, the following query is only a good guess. The bits to notice and work with are sum() and GROUP BY. Actually syntax will vary a bit depending on what RDBMS you are using.
SELECT
date
,operator
,SUM(total_working_time_h) AS total_working_time_h
,SUM(no_of_defects) AS no_of_defects
FROM {$table_work_hours}
WHERE date = '2016-06-03'
GROUP BY
date
,operator
(Take out the WHERE clause or replace it with a range of dates to get results per operator per date.)
I'm not sure why you are trying to do DISTINCT. You want to know the data, no of hours, etc for a specific date.
do this....
Select Date, Operator, 'SumWorkHrs'=sum(total_working_time_h),
'SumDefects'=sum(no_ofDefects) from {$table_work_hours}
Where date='2016-06-03'
Try this:
SELECT SUM(total_working_time) as total_working_time,
SUM(no_of_defects) as no_of_defects ,
DISTINCT(operator) AS operator FROM {$table_work_hours} WHERE
date = '2016-06-03'
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'
I am trying to add months to an existing date in SQL. The new column displayed will have a followup column instead of a days column. Im getting an error in the select statement.can u help?
Create table auctions(
item varchar2(50),
datebought date,
datesold date,
days number
);
Insert into auctions values (‘Radio’,’12-MAY-2001’,’21-MAY-2001’,9);
Select item,datebought,datesold,ADD MONTHS(datesold,3)”followup” from auctions;
Your usage of the add_months() function is incorrect. It's not two words, it's just one (with an underscore)
add_months(datesold, 1)
note the underscore _ between ADD and MONTHS. It's function call not an operator.
Alternatively you could use:
datesold + INTERVAL '1' month
Although it's worth noting that the arithmetics with intervals is limited (if not broken) because it simply "increments" the month value of the date value. That can lead to invalid dates (e.g. from January to February). Although this is documented behaviour (see below links) I consider this a bug (the SQL standard requires those operations to "Arithmetic obey the natural rules associated with dates and times and yield valid datetime or interval results according to the Gregorian calendar")
See the manual for details:
http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions011.htm#i76717
http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements001.htm#i48042
Another thing:
I am trying to add months to an existing date in SQL.
Then why are you using an INSERT statement? To change the data of existing rows you should use UPDATE. So it seems what you are really after is something like this:
update auctions
set datesold = add_months(datesold, 1)
where item = 'Radio';
Your SQL has typographical quotation marks, not standard ones. E.g. ’ is not the same as '. Instead of delimiting a string value, those quotes become part of the value, at least for the particular SQL I have here to test with.
If this doesn't fix your problem, try posting the error you're getting in your question. Magical debugging isn't possible.
This can be used to add months to a date in SQL:
select DATEADD(mm,1,getdate())
This might be a useful link.
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.