How do I write this Cloudsearch query - amazon-cloudsearch

I have cloudsearch records with the following fields (among others):
status: eg 'PROPPOSAL', 'ACCEPTED', 'CANCELLED' etc
created_at: eg 2018-06-29T11:03:44Z
I need a query that can satisfy the following:
No proposals older than 31 days
How do I write that as a query? At the moment I seem only to be able to write queries that return ONLY records where the status is not PROPOSAL or queries that return only records that are younger than 31 days
Both of which are wrong.
The query should return records regardless of date UNLESS they are PROPOSAL, in which case apply the 31 days rule as well.
How can I do this? I tried something like:
(and
(and
(range field=created_at ['2019-07-21T14:31:30Z',})
(not field=status 'PROPOSAL')
)
)
Which does not do what I need

Related

Running an Access query on a FILTERED table

I have some related tables that I want to run a Totals/Group By query on.
My "Tickets" table has a field called "PickDate" which is the date that the order/ticket was fulfilled.
I want to group by the weekday (name) (a calculated field) so that results for certain customers on the same day of the week are grouped. Then the average ticket completion time can be calculated per customer for each weekday. It would look something like the following.
--CustName---Day---AvTime
Customer 1 - MON - 72.3
- TUE - 84.2
- WED - 110.66
..etc
..etc
..etc
Customer 2 ..
This works fine but the problem I am having is that when this query is run, it works on every record from the tickets table. There are some reasons that, for certain reports, the data that it the query is referencing should be restricted between a date range; for example to track a change in duration over a number of weeks.
In the query properties, there is a property, "filter", to which I can add a string such as:
"([qryCustomerDetails].[PickDate] Between #11/1/2021# And #11/14/2021#)"
to filter the results. The only issue is that since each date is unique, the "group by" of like days such as "Monday" is overridden by this unique date "11/1/2021". The query only works when the PickDate is removed as a field. However, then I can't access it to filter by it.
What I want to achieve would be the same as; in the "Tickets" table itself filtering the results between two dates and then having a query that could run on that filtered table.
Is there any way that I could achieve this?
For reference here is the SQL of the query.
FROM tblCustomers INNER JOIN tblTickets ON tblCustomers.CustomerID = tblTickets.CustomerID
GROUP BY tblCustomers.Customer, WeekdayName(Weekday([PickDate]),False,1), tblCustomers.Round, Weekday([PickDate])
ORDER BY tblCustomers.Round, Weekday([PickDate]);
You probably encountered two issues. The first issue is that to filter results in a totals query by un totaled fields you use HAVING rather than WHERE. the second issue is that calculated fields like Day don't exist at the time of the query. You can't say having Day > Mon. Instead you must repeat the calculation of Day: Having CalculateDay(PickDate) > Monday
The designer will usually figure out whether you want having or where automatically. So here is my example:
this gives you the SQL:
SELECT Tickets.Customer, WeekdayName(Weekday([PickDate])) AS [Day], Avg(Tickets.Time) AS AvTime
FROM Tickets
GROUP BY Tickets.Customer, WeekdayName(Weekday([PickDate])), Tickets.PickDate
HAVING (((Tickets.PickDate) Between #11/16/2021# And #11/17/2021#))
ORDER BY Tickets.PickDate;

Weird query result when filtering dates in SQL

I have a 40 thousand rows .csv file of football matches with dates on each game. I have formatted the dates column in 'YY-MM-DD' format with lubridate in R, so every row is like that and checked if it's in Date class, which it is.
After that I just saved the .csv file (with fwrite function in data.table) and added it to my database which is in sqlite3.
When I run this query:
-- The important part is the WHERE clause
SELECT dates, home_team, away_team, home_score, away_score, city, country FROM History_games
WHERE dates < '19300713'
To filter and get games before the 13th of July of 1930. The query runs but I get matches up to: 1930-12-07 (which is the 7th of December 1930).
If I use 19301307 (which would be wrong) the same result comes back.
I did the same filter in R with lubridate and in Python with pandas and there was no problem. My last row is 1930-07-06 (July the 6th of 1930), which is the correct date.
Could somebody tell me what is wrong with the query? I have tried it in db browser sqlite3 and datagrip and both of them throw the same result.
Thanks

SQL Query to find instances within 60 days of an earlier instance

I have a table with Result Dates, Result Values and User IDs. I am looking for a way to find the people (number and specifics) that had result values greater than a number (20) that ALSO had a follow up result within 60 days of their initial result.
I have no problem getting the list of people with the result greater than 20, just don't know how to also find the people that were re-tested within 60 days and have a result.
I am very, very new to SQL, not sure what else is needed to help...thanks!!!

advise on schema design

I want to store the opening and closing hours of locations into a DB table. Which of the following table design do you think is more ideal? I'm using MySQL or and maybe PostgreSQL (Would it matter?).
One record per day? (returns 1-7 results)
id, location_id, weekday, start_time, closing_time
Or one record per location? (returns 1 result always)
id, location_id, mon_start, mon_end, tue_start, tue_end, ... ... ... sun_start, sun_end
The most common query will simply to display the contents like this (always the entire week):
Location: blablabla
Operating Hours:
Monday: 8 AM to 8 PM
... ...
Sunday: 8 AM to 12 PM
The first solution is clearly correct. The second one is not normalized, harder to program against, and not extendable (for holidays, special hours, etc).
Definitely the first, it's better normalised and you could easily produce the data in the second format using a lookup table for the days and perhaps a view.
As the first poster states, the first solution could easily be extended to include holidays, etc. The second is not so flexible.

Best way in MySQL or Rails to get AVG per day within a specific date range

I'm trying to make a graph in Rails, for example the avg sales amount per day for each day in a given date range
Say I have a products_sold model which has a "sales_price" float attribute. But if a specific day has no sales (e.g none in the model/db), I want to return simply 0.
What's the best way in MySQL/Rails to get this done? I know I can do something like this:
(This SQL query might be the completely wrong way to get what I'm wanting too)
SELECT avg(sales_price) AS avg, DATE_FORMAT(created_at, '%m-%d-%Y') AS date
FROM products_sold WHERE merchant_id = 1 GROUP BY date;
And get results like this:
| avg | date |
23 01-03-2009
50 01-05-2009
34 01-07-2009
... ...
What I'd like to get is this:
| avg | date |
23 01-03-2009
0 01-04-2009
50 01-05-2009
0 01-06-2009
34 01-07-2009
0 01-08-2009
... ...
Can I do this with SQL or will I have to post-process the results to find what dates in the daterange aren't in the SQL result set? Perhaps I need some sub-selects or IF statements?
Thanks for any help everyone.
Is there a reason (other than the date one already mentioned) why you wouldn't use the built-in group function capabilities in ActiveRecord? You seem to be concerned about "post-processing", which I don't think is really something to worry about.
You're in Rails, so you should probably be looking for a Rails solution first[1]. My first thought would be to do something like
Product.average(:sales_price, :group => "DATE(created_at)", :conditions => ["merchant_id=?", 1])
which ActiveRecord turned into pretty much the SQL you described. Assuming there's a declared has_many association between Merchant and Product, then you'd probably be better using that, so something like:
ave_prices = Merchant.find(1).products.average(:sales_price, :group => "DATE(created_at)")
(I'm hoping that your description of the model as "products_sold" is some kind of transcription error, btw - if not, you're somewhat off-message with your class naming!)
After all that, you're back where you started, but you got there in a more conventional Rails way (and Rails really values conventions!). Now we need to fill in the gaps.
I'll assume you know your date range, let's say it's defined as all dates from from_date to to_date.
date_aves = (from_date..to_date).map{|dt| [dt, 0]}
That builds the complete list of dates as an array. We don't need the dates where we got an average:
ave_price_dates = ave_prices.collect{|ave_price| ave_price[0]} # build an array of dates
date_aves.delete_if { |dt| ave_price.dates.index(dt[0]) } # remove zero entries for dates retrieved from DB
date_aves.concat(ave_prices) # add the query results
date_aves.sort_by{|ave| ave[0] } # sort by date
That lot looks a bit cluttered to me: I think it could be terser and cleaner. I'd investigate building a Hash or Struct rather than staying in arrays.
[1] I'm not saying don't use SQL - situations do occur where ActiveRecord can't generate the most efficient query and you fall back on find_by_sql. That's fine, it's supposed to be like that, but I think you should try to use it only as a last resort.
For any such query, you will need to find a mechanism to generate a table with one row for each date that you want to report on. Then you will do an outer join of that table with the data table you are analyzing. You may also have to play with NVL or COALESCE to convert nulls into zeroes.
The hard part is working out how to generate the (temporary) table that contains the list of dates for the range you need to analyze. That is DBMS-specific.
Your idea of mapping date/time values to a single date is spot on, though. You'd need to pull a similar trick - mapping all the dates to an ISO 8601 date format like 2009-W01 for week 01 - if you wanted to analyze weekly sales.
Also, you would do better to map your DATE format to 2009-01-08 notation because then you can sort in date order using a plain character sort.
To dry up a bit:
ave_prices = Merchant.find(1).products.average(:sales_price, :group => "DATE(created_at)")
date_aves = (from_date..to_date).map{|dt| [dt, ave_prices[dt.strftime "%Y-%m-%d"] || 0]}
Does MySQL have set-returning functions? I.e. functions that return different values on each row of a query? As an example from PostgreSQL, you can do:
select 'foo', generate_series(3, 5);
This will produce a result set consisting of 2 columns and 3 rows, where the left column contains 'foo' on each row and the right column contains 3, 4 and 5.
So, assuming you have an equivalent of generate_series() in MySQL, and subqueries: What you need is a LEFT OUTER JOIN from this function to the query that you already have. That will ensure you see each date appear in the output:
SELECT
avg(sales_price) as avg,
DATE_FORMAT(the_date, '%m-%d-%Y') as date
FROM (select cast('2008-JAN-01' as date) + generate_series(0, 364) as the_date) date_range
LEFT OUTER JOIN products_sold on (the_date = created_at)
WHERE merchant_id = 1
GROUP BY date;
You may need to fiddle with this a bit to get the syntax right for MySQL.