Postgres - Select all rows with a date column value within a range of another row's value? - postgresql

I'm trying to use a date value as a starting point to construct a date range within a single postgres query. The date value would be something like
SELECT upgraded_at FROM accounts ORDER BY upgraded_at DESC limit 1;
which would then be used as the starting point. I then want to do something like
SELECT * from accounts WHERE upgraded_at >= (basis_date - 2 days) AND upgraded_at < (basis_date + 2 days);
Ideally I'd like to accomplish this with a single query. So I'll need to some subquery to get the starting date, then use that as a variable within the rest of the query.
Also eventually I'm going to be doing this within Sequelize. I definitely need the raw SQL way to do it but I'm also curious if later there's a Sequelize-specific way.

You can actually avoid making two references to the basis date here.
WITH cte AS (
SELECT *, MAX(upgraded_at) OVER () AS max_upgraded_at
FROM accounts
)
SELECT *
FROM cte
WHERE upgraded_at - max_upgraded_at BETWEEN -2 AND 2;

Related

Looking to populate the values in between two consecutive rows and its corresponding value for another column in postgres

I guess I have a simple ask but I am not sure about its implementation in postgreSQL query.
I have a table already present I am using which is as follows -
I am looking to fill in the values in between two consecutive wind_speed and its corresponding value in power_kw so that I can use these values in CTE (common table expression) for further use. (P.S. I don't want to create an extra table in database)
The output I am looking is as follows -
If it's always a 0.5 increment between the wind_speed values, then I think something like this would work:
select
power_curve_id,
generate_series (wind_speed, wind_speed + 0.49, 0.01) as wind_speed,
power_kw +
(lead (power_kw) over (partition by power_curve_id order by wind_speed) - power_kw) / 50 *
generate_series (0, 49) as power_kw
from power p
If that's not a safe assumption, please indicate so... there are ways

Postgres combining date and time fields, is this efficient

I am selecting rows based on a date range which is held in a string using the below SQL which works but is this a efficient way of doing it. As you can see the date and time is held in different fields. From my memory or doing Oracle work as soon as you put a function around a attribute it cant use indexes.
select *
from events
where venue_id = '2'
and EXTRACT(EPOCH FROM (start_date + start_time))
between EXTRACT(EPOCH FROM ('2017-09-01 00:00')::timestamp)
and EXTRACT(EPOCH FROM ('2017-09-30 00:00')::timestamp)
So is there a way of doing this that can use indexes?
Preface: Since your query is limited to a single venue_id, both examples below create a compound index with venue_id first.
If you want an index for improving that query, you can create an expression index:
CREATE INDEX events_start_idx
ON events (venue_id, (EXTRACT(EPOCH FROM (start_date + start_time))));
If you don't want a dedicated function index, you can create a normal index on the start_date column, and add extra logic to use the index. The index will then limit access plan to date range, and fringe records with wrong time of day on first and last dates are filtered out.
In the following, I'm also eliminating the unnecessary extraction of epoch.
CREATE INDEX events_venue_start
ON events (venue_id, start_date);
SELECT *
FROM events
WHERE venue_id = '2'
AND start_date BETWEEN '2017-09-01'::date AND '2017-09-30'::date
AND start_date + start_time BETWEEN '2017-09-01 00:00'::timestamp
AND '2017-09-30 00:00'::timestamp
The first two parts of the WHERE clause will use the index to full benefit. the last part is then use the filter the records found by the index.

How do I sort partition data when using query binding on an SSAS cube?

I'm trying to implement various sorts as described in this article.
I have a typical Sales Measure Group partitioned by fiscal period. If I try to add an order by clause to the query it fails when processing because SSAS wraps the query into a subquery. Is there a way to prevent this from happening? How do I ensure the sort order in a case like this?
Here is the code that is generated for a partition:
SELECT *
FROM
(
SELECT *
FROM [Sales]
WHERE SaleDate between '1/1/2015' and '1/28/2015'
order by SaleDate
)
AS [Sales]
I replaced the field names with * for clarity.
SELECT TOP 100 PERCENT * FROM Sales ORDER BY SaleDate
That is not guaranteed to work. The best way to order it is to ensure the clustered index is on the column you want to order by.

Order by custom named rows

I’d like to sort my postgres results by some fancy ranking function, but for sake of simplicity, let’s say that I’d like to add two custom rows and sort by them.
SELECT my_table.*,
extract(epoch from (age(current_date, '2012-09-12 10:43:40'::date)))/3600 AS age_in_hours
Fancy_function_counting_distance() AS distance
FROM my_table
ORDER BY distance + age_in_hours;
However, it doesn’t work, since I’m getting error: ERROR: column "distance" does not exist.
Is it possible to order my results by that custom named rows?
I’m running postgres 9.1.x
As per the SQL standard, aliases in the SELECT list are not visible in ORDER BY.
You can use column-position specification (eg ORDER BY 1,2), but that doesn't accept an expression; you cannot ORDER BY 1+2, for example. So you need to use a subquery to generate the result set then sort it in an outer query:
SELECT *
FROM (
SELECT my_table.*,
extract(epoch from (age(current_date, '2012-09-12 10:43:40'::date)))/3600 AS age_in_hours
Fancy_function_counting_distance() AS distance
FROM my_table
) x
ORDER BY distance + age_in_hours;

how do you sum over a related period

I need to sum values that are + 2 months or within a quarter period (related date table)
is there a way to use dense rank to partition those periods (custom periods)?
select
FiscalMonth
,Value
from table
The sql will have to do the following:
Join the value table and the period table
Include the period in the select list and sum the value, grouping by the period
i.e
select b.period, sum(a.value)
from table a
inner join period b on a.FiscalMonth between b.StartMonth and b.EndMonth
group by b.period
Note: The join condition will have to be modified based on what data you actually have in the period table.
Hope this helps
Well, If you need value from an X interval, by month you could use something like:
SELECT *
FROM yourTable
MONTH(some_date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH) //Could be X interval!
This is an example (which show the results of the previous month, from the actual one). Just trying to write that it is possible to massage the query in functions on intervals.
Of course, you could use the SUMcommand for the adding.