Hello Guys I am trying to convert following script from MS SQL to PostgreSQL but unable to convert the starred ones in the below script
WITH procedurerange_cte AS (
select distinct
accountsize as HospitalSize
,min(catprocsannualintegratedallpayer) over (partition by accountsize) as MinProcsPerAcct
,max(catprocsannualintegratedallpayer) over (partition by accountsize) as MaxProcsPerAcct
from sandbox.vw_hopd_universe_1_ms
group by accountsize,catprocsannualintegratedallpayer
), accts_cte AS (
select
accountsize as HospitalSize
,count(master_id) as Count
,sum(catprocsannualintegratedallpayer) as catprocsannualintegratedallpayer
from sandbox.vw_hopd_universe_1_ms
group by accountsize
), allcatprocs_cte AS (
select
sum(catprocsannualintegratedallpayer) as AllAnnCatProcs
from sandbox.accts_universeaccts
), totals_cte AS (
select
case when HospitalSize is null then 'Total' else HospitalSize end as HospitalSize
,sum(Count) as Count
,sum(catprocsannualintegratedallpayer) as catprocsannualintegratedallpayer
from accts_cte
group by grouping sets ((HospitalSize,Count,catprocsannualintegratedallpayer),())
)
select
a.HospitalSize
,a.Count
***--,convert(float,a.Count)/convert(float,(select Count from totals_cte where HospitalSize='Total')) as %OfHospitals***
,a.catprocsannualintegratedallpayer as HospitalAnnCatProcs
***--,a.catprocsannualintegratedallpayer/(select catprocsannualintegratedallpayer from totals_cte where HospitalSize='Total') as %OfHospProcs***
***--,a.catprocsannualintegratedallpayer/(select AllAnnCatProcs from allCatProcs_cte) as %OfAllProcs***
,MinProcsPerAcct
,MaxProcsPerAcct
,***CASE
when a.HospitalSize='Large' then '8 to 10'
when a.HospitalSize='Medium' then '5 to 7'
when a.HospitalSize='Small' then '0 to 4'
end as DecilesIncluded***
from totals_cte as a
left join procedurerange_cte as b
on a.HospitalSize=b.HospitalSize
Please help in converting the above script to PostgreSQL as I am new to this field
Related
I am working with a database and am using the following query:
SELECT
evt_block_time,
COUNT(*) filter (
WHERE
uniswap_version = 'v1'
) OVER (
ORDER BY
evt_block_time
) as v1_pairs,
COUNT(*) filter (
WHERE
uniswap_version = 'v2'
) OVER (
ORDER BY
evt_block_time
) as v2_pairs
FROM
(
SELECT
'v2' as uniswap_version,
evt_block_time
FROM
uniswap_v2."Factory_evt_PairCreated"
UNION ALL
SELECT
'v1' as uniswap_version,
evt_block_time
FROM
uniswap."Factory_evt_NewExchange"
ORDER BY
evt_block_time
) as creations
Here's a glimpse at what it returns:
I would like to do a few things. First of all, truncate the timestamps, evt_block_time, by week and then group by week.
NOTE: I tried using date_trunc('week', evt_block_time) under each of my select statements, but it throws an error. See below:
SELECT
date_trunc('week', evt_block_time),
COUNT(*) filter (
WHERE
uniswap_version = 'v1'
) OVER (
ORDER BY
evt_block_time
) as v1_pairs,
COUNT(*) filter (
WHERE
uniswap_version = 'v2'
) OVER (
ORDER BY
evt_block_time
) as v2_pairs
FROM
(
SELECT
'v2' as uniswap_version,
date_trunc('week', evt_block_time)
FROM
uniswap_v2."Factory_evt_PairCreated"
UNION ALL
SELECT
'v1' as uniswap_version,
date_trunc('week', evt_block_time)
FROM
uniswap."Factory_evt_NewExchange"
ORDER BY
evt_block_time
) as creations
which returns:
Column "evt_block_time" does not exist at line 31, position 26.
Additionally, though I guess it's not required, I would like to only query data from the last 52 weeks (1 year).
Obviously, I'm kinda new to this SQL thing but I'm trying my best. Any help whatsoever would be appreciated!
The problem is you're selecting evt_block_time from the subquery, but the subquery no longer contains evt_block_time, it contains date_trunc('week', evt_block_time).
To fix this, give it a name like evt_block_week and select that.
Since it's a calculated column you can't order by it, but the order by in the subquery does nothing. Remove it. If you want to apply an order, do it in surrounding query.
The orders in the count filters also do nothing, order doesn't matter for a count. Remove them.
Finally, to get the number of each version of timestamp per week, group by evt_block_week. And also order by evt_block_week.
SELECT
evt_block_week,
COUNT(*) filter (
WHERE
uniswap_version = 'v1'
) as v1_pairs,
COUNT(*) filter (
WHERE
uniswap_version = 'v2'
) as v2_pairs
FROM
(
SELECT
'v2' as uniswap_version,
date_trunc('week', evt_block_time) as evt_block_week
FROM
uniswap_v2."Factory_evt_PairCreated"
UNION ALL
SELECT
'v1' as uniswap_version,
date_trunc('week', evt_block_time) as evt_block_week
FROM
uniswap."Factory_evt_NewExchange"
) as creations
group by evt_block_week
order by evt_block_week
If you want to only do a range of weeks, use generate_series to generate a list of weeks. If you want to see all weeks, use that as the from sub-query and left join with creations. Order and group by the generated week.
SELECT
weeks.week,
COUNT(*) filter (
WHERE
uniswap_version = 'v1'
) as v1_pairs,
COUNT(*) filter (
WHERE
uniswap_version = 'v2'
) as v2_pairs
from (
select
generate_series(
date_trunc('week', '2020-01-01'::date), date_trunc('week', '2020-12-31'::date), '1 week'
) as week
) as weeks
left join
(
SELECT
'v2' as uniswap_version,
date_trunc('week', evt_block_time) as evt_block_week
FROM
uniswap_v2."Factory_evt_PairCreated"
UNION ALL
SELECT
'v1' as uniswap_version,
date_trunc('week', evt_block_time) as evt_block_week
FROM
uniswap."Factory_evt_NewExchange"
) as creations on weeks.week = evt_block_week
group by week
order by week
Demonstration.
Your subquery creations does not have a column with alias evt_block_time, consequently you cannot use that column name in the main query.
I want to get the number of consecutive days from the current date using Postgres SQL.
enter image description here
Above is the scenario in which I have highlighted consecutive days count should be like this.
Below is the SQL query which I have created but it's not returning the expected result
with grouped_dates as (
select user_id, created_at::timestamp::date,
(created_at::timestamp::date - (row_number() over (partition by user_id order by created_at::timestamp::date) || ' days')::interval)::date as grouping_date
from watch_history
)
select * , dense_rank() over (partition by grouping_date order by created_at::timestamp::date) as in_streak
from grouped_dates where user_id = 702
order by created_at::timestamp::date
Can anyone please help me to resolve this issue?
If anyhow we can able to apply distinct for created_at field to below query then I will get solutions for my issue.
WITH list AS
(
SELECT user_id,
(created_at::timestamp::date - (row_number() over (partition by user_id order by created_at::timestamp::date) || ' days')::interval)::date as next_day
FROM watch_history
)
SELECT user_id, count(*) AS number_of_consecutive_days
FROM list
WHERE next_day IS NOT NULL
GROUP BY user_id
Does anyone have an idea how to apply distinct to created_at for the above mentioned query ?
To get the "number of consecutive days" for the same user_id :
WITH list AS
(
SELECT user_id
, array_agg(created_at) OVER (PARTITION BY user_id ORDER BY created_at RANGE BETWEEN CURRENT ROW AND '1 day' FOLLOWING) AS consecutive_days
FROM watch_history
)
SELECT user_id, count(DISTINCT d.day) AS number_of_consecutive_days
FROM list
CROSS JOIN LATERAL unnest(consecutive_days) AS d(day)
WHERE array_length(consecutive_days, 1) > 1
GROUP BY user_id
To get the list of "consecutive days" for the same user_id :
WITH list AS
(
SELECT user_id
, array_agg(created_at) OVER (PARTITION BY user_id ORDER BY created_at RANGE BETWEEN CURRENT ROW AND '1 day' FOLLOWING) AS consecutive_days
FROM watch_history
)
SELECT user_id
, array_agg(DISTINCT d.day ORDER BY d.day) AS list_of_consecutive_days
FROM list
CROSS JOIN LATERAL unnest(consecutive_days) AS d(day)
WHERE array_length(consecutive_days, 1) > 1
GROUP BY user_id
full example & result in dbfiddle
I'm using SQL Server 2000 (80). So, it's not possible to use the LAG function.
I have a code a data set with four columns:
Purchase_Date
Facility_no
Seller_id
Sale_id
I need to identify missing Sale_ids. So every sale_id is a 100% sequential, so the should not be any gaps in order.
This code works for a specific date and store if specified. But i need to work on entire data set looping looping through every facility_id and every seller_id for ever purchase_date
declare #MAXCOUNT int
set #MAXCOUNT =
(
select MAX(Sale_Id)
from #table
where
Facility_no in (124) and
Purchase_date = '2/7/2020'
and Seller_id = 1
)
;WITH TRX_COUNT AS
(
SELECT 1 AS Number
union all
select Number + 1 from TRX_COUNT
where Number < #MAXCOUNT
)
select * from TRX_COUNT
where
Number NOT IN
(
select Sale_Id
from #table
where
Facility_no in (124)
and Purchase_Date = '2/7/2020'
and seller_id = 1
)
order by Number
OPTION (maxrecursion 0)
My Dataset
This column:
case when
Sale_Id=0 or 1=Sale_Id-LAG(Sale_Id) over (partition by Facility_no, Purchase_Date, Seller_id)
then 'OK' else 'Previous Missing' end
will tell you which Seller_Ids have some sale missing. If you want to go a step further and have exactly your desired output, then filter out and distinct the 'Previous Missing' ones, and join with a tally table on not exists.
Edit: OP mentions in comments they can't use LAG(). My suggestion, then, would be:
Make a temp table that that has the max(sale_id) group by facility/seller_id
Then you can get your missing results by this pseudocode query:
Select ...
from temptable t
inner join tally N on t.maxsale <=N.num
where not exists( select ... from sourcetable s where s.facility=t.facility and s.seller=t.seller and s.sale=N.num)
> because the only way to "construct" nonexisting combinations is to construct them all and just remove the existing ones.
This one worked out
; WITH cte_Rn AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY Facility_no, Purchase_Date, Seller_id ORDER BY Purchase_Date) AS [Rn_Num]
FROM (
SELECT
Facility_no,
Purchase_Date,
Seller_id,
Sale_id
FROM MyTable WITH (NOLOCK)
) a
)
, cte_Rn_0 as (
SELECT
Facility_no,
Purchase_Date,
Seller_id,
Sale_id,
-- [Rn_Num] AS 'Skipped Sale'
-- , case when Sale_id = 0 Then [Rn_Num] - 1 Else [Rn_Num] End AS 'Skipped Sale for 0'
, [Rn_Num] - 1 AS 'Skipped Sale for 0'
FROM cte_Rn a
)
SELECT
Facility_no,
Purchase_Date,
Seller_id,
Sale_id,
-- [Skipped Sale],
[Skipped Sale for 0]
FROM cte_Rn_0 a
WHERE NOT EXISTS
(
select * from cte_Rn_0 b
where b.Sale_id = a.[Skipped Sale for 0]
and a.Facility_no = b.Facility_no
and a.Purchase_Date = b.Purchase_Date
and a.Seller_id = b.Seller_id
)
--ORDER BY Purchase_Date ASC
I have 3 tables:
with current_exclusive as(
select id_station, area_type,
count(*) as total_entries
from c1169.data_cashier
where id_station IN(2439,2441,2443,2445,2447,2449) and date >= '2017-10-30' and date <= '2017-12-30'
group by id_station, area_type
), current_table as(
select id_station, area_type,
sum(total_time) filter (where previous_status = 1) as total_time
from c1169.data_table
where id_station IN(2439,2441,2443,2445,2447,2449) and date >= '2017-10-30' and date < '2017-12-30'
group by id_station, area_type
), current_cashier as(
select id_station, area_type,
sum(1) as total_transactions
from c1169.data_cashier
where id_station IN(2439,2441,2443,2445,2447,2449) and date >= '2017-10-30' and date < '2017-12-30'
group by id_station, area_type
)
select *
from current_exclusive
full join current_table on current_exclusive.id_station = current_table.id_station and current_exclusive.area_type = current_table.area_type
full join current_cashier on current_exclusive.id_station = current_cashier.id_station and current_exclusive.area_type = current_cashier.area_type
and the result is:
but my expected result is:
Are there any way to select * and show the expected result? Because when I do full join then id_station and area_type can be null in some tables, so it very hard to choose which column is not null.
Like: select case id_station is not null then id_station else id_station1 end, but I have up to 10 tables so can not do in select case
Use USING, per the documentation:
USING ( join_column [, ...] )
A clause of the form USING ( a, b, ... ) is shorthand for ON left_table.a = right_table.a AND left_table.b = right_table.b .... Also, USING implies that only one of each pair of equivalent columns will be included in the join output, not both.
select *
from current_exclusive
full join current_table using (id_station, area_type)
full join current_cashier using (id_station, area_type)
You cannot accomplish anything if you insist on using select *, since you are getting the values from different tables.
The option you have is to include a COALESCE block which gives you the first non-null value from the list of columns.
So, you could use.
select COALESCE( current_exclusive.id_station, current_table.id_station, current_cashier.id_station ) as id_station ,
COALESCE( current_exclusive.area_type , current_table.area_type, current_cashier.area_type ) as area_type ,.....
...
from current_exclusive
full join current_table..
...
I'm going to post my query at the end of this post here, but just exposition is required first. Please ignore the column names and table names but I have syntax errors in two spots. When I put this query with my CTE it tells me I have to first 'terminate the previous statement with a ;' Then I go onto alias a column name in the CTE and then it says 'The multi-part identifier "E.ActiveAGVs" could not be bound.'
I hope that I am explaining my problem well enough. If anyone can see what I'm trying to do and let me know if it will work or correct my syntax errors, I would really appreciate it.
Select A.move_hour as 'Hour',
isnull(B.move_count,0) as 'Current_Count',
isnull(C.move_count,0) as '1_Day_Previous',
isnull(D.move_count,0) as '2_Day_Previous',
ISNULL (E.ActiveAGVs,0) as 'Active AGV''s'
--^ Error right here
from
(select distinct(DATEPART(HH, Move_History.Move_Dt)) as move_hour
from Move_History
where Plant_Id = 1 and Building_Id = 1) as A
left outer join
(select datepart(HH,Move_History.Move_Dt) as move_hour,
Move_History.Move_Cnt as move_count
from Move_History
Group by datepart(HH,Move_History.Move_Dt), Move_Cnt) as B on A.move_hour = B.move_hour
left outer join
(select datepart(HH,Move_History.Move_Dt) as move_hour, Move_History.Move_Cnt as move_count
from Move_History
Group by datepart(HH,Move_History.Move_Dt), Move_Cnt) as C on A.move_hour = C.move_hour
left outer join
(select datepart(HH,Move_History.Move_Dt) as move_hour, Move_History.Move_Cnt as move_count
from Move_History
Group by datepart(HH,Move_History.Move_Dt), Move_Cnt) as D on A.move_hour = D.move_hour;
with const as (
select cast(cast(getdate() as date) as datetime) as midnight
),
allhours as (
select 0 as m_hour, midnight as timestart, dateadd(hour, 1, midnight) as timeend from const union all
...
select 23 as m_hour, dateadd(hour, 23, midnight) as timestart, dateadd(hour, 24, midnight) as timeend from const
)
(select ah.m_hour,
(sum(datediff(SECOND, timestart), ah.timeend else dt.End_Dt end))
/ 18000.0) * 5 as ActiveAGVs
from allhours as ah
left outer join AGV_Report as dt
on ah.timestart< coalesce(dt.End_dt, getdate()) and
ah.timeend >= dt.Begin_Dt
Group by datepart(SECOND,ah.hour), ah.timestart) as E on A.move_hour = E.move_hour
--^ 'Incorrect syntax near "as"'
where A.move_hour is not null
order by ah.m_hour asc
All CTEs that you need to define for a statement, must go at the beginning of the statement. Even though the CTEs are going to be used only in one of the subqueries, the syntax still requires them to be placed at the beginning of the entire statement, not at the beginning of the particular subquery where they are actually referenced.
Therefore, your statement should probably look something like this:
; -- required if there are statements preceding
with const as (
select cast(cast(getdate() as date) as datetime) as midnight
),
allhours as (
select
0 as m_hour,
midnight as timestart,
dateadd(hour, 1, midnight) as timeend
from const
union all
...
select
23 as m_hour,
dateadd(hour, 23, midnight) as timestart,
dateadd(hour, 24, midnight) as timeend
from const
)
Select A.move_hour as 'Hour',
isnull(B.move_count,0) as 'Current_Count',
isnull(C.move_count,0) as '1_Day_Previous',
isnull(D.move_count,0) as '2_Day_Previous',
ISNULL (E.ActiveAGVs,0) as 'Active AGV''s'
from
(
select distinct
DATEPART(HH, Move_History.Move_Dt) as move_hour
from Move_History
where Plant_Id = 1 and Building_Id = 1
) as A
left outer join
(
select
datepart(HH,Move_History.Move_Dt) as move_hour,
Move_History.Move_Cnt as move_count
from Move_History
Group by datepart(HH,Move_History.Move_Dt), Move_Cnt
) as B on A.move_hour = B.move_hour
left outer join
(
select
datepart(HH,Move_History.Move_Dt) as move_hour,
Move_History.Move_Cnt as move_count
from Move_History
Group by datepart(HH,Move_History.Move_Dt), Move_Cnt
) as C on A.move_hour = C.move_hour
left outer join
(
select
datepart(HH,Move_History.Move_Dt) as move_hour,
Move_History.Move_Cnt as move_count
from Move_History
Group by datepart(HH,Move_History.Move_Dt), Move_Cnt
) as D on A.move_hour = D.move_hour
left outer join -- assuming...
(
select
ah.m_hour,
(sum(datediff(SECOND, timestart), ah.timeend else dt.End_Dt end))
/ 18000.0) * 5 as ActiveAGVs
from allhours as ah
left outer join AGV_Report as dt
on ah.timestart < coalesce(dt.End_dt, getdate())
and ah.timeend >= dt.Begin_Dt
Group by datepart(SECOND,ah.hour), ah.timestart
) as E on A.move_hour = E.move_hour
where A.move_hour is not null
order by ah.m_hour asc
A common table expression (CTE) must be separated from any prior statement by a semicolon (;). If no statements precede the with then there is no need for a semicolon.
You can have multiple CTEs within a single with. An example follows:
with
-- Counting numbers.
Numbers as (
select 1 as Number
union all
select Numbers.Number + 1
from Numbers
where Number < 10 ),
-- Squares of counting numbers.
Squares as (
select Number, Number * Number as Square
from Numbers )
-- Result.
select Number, Square
from Squares
Like the rest of the people trying to help, I have no idea of what your SQL is trying to do.