ORA-00937 not a single-group group function converted from SQL Server - sql

I'm getting an ORA-00937 error when running the following ORACLE statement, I'm very new to Oracle (T-SQL is more my bag). I've converted a select statement previously written in SQL I'm at a loss as to why it's expecting a group by ... as all columns are sum'd. This is the converted select statement (I'm currently running/ testing these using SQLPLUS) :
select
round(COALESCE(
(COALESCE((select SUM((F_BOOK_DATES.BKD_ADATE_ENDS - F_BOOK_DATES.BKD_ADATE_START) * (60 * 24)) FROM F_BOOK_DATES
INNER JOIN F_BOOK_HEADER ON F_BOOK_DATES.BKD_FKEY_BK_SEQ = F_BOOK_HEADER.BK_SEQ
and EXTRACT (YEAR from F_BOOK_DATES.BKD_DATE_START ) = EXTRACT (YEAR from SYSDATE )
and EXTRACT (MONTH from F_BOOK_DATES.BKD_DATE_START ) = EXTRACT (MONTH from SYSDATE )
and EXTRACT (DAY from F_BOOK_DATES.BKD_DATE_START ) = EXTRACT (DAY from SYSDATE )
AND F_BOOK_HEADER.BK_STATUS NOT IN ('CX','TP')
AND F_BOOK_HEADER.Deleted <> 1
AND F_BOOK_DATES.Deleted <> 1),9999999999.99,0)
/sum(case when FAREALO.AllDayBooking = 1 then 1400 else
((FAREALO.LO_TIME_END - FAREALO.LO_TIME_START) * (60 * 24)) end) * 100),0),2) as "PercentUtilised"
from FAREALO
inner join F_LO_TYPE on FAREALO.LO_FKEY_LOT_SEQ = F_LO_TYPE.LOT_SEQ
where FAREALO.LO_BK_LOCATION = 1
and LOT_CBS = 1;
This is the SQL statement (that works) that I tried to convert above:
select
round(isnull(
(isnull(convert (DECIMAL(10,2),(select SUM(datediff(n,BKD_ADATE_START, BKD_ADATE_ENDS)) FROM F_BOOK_DATES with (NOLOCK)
INNER JOIN F_BOOK_HEADER with (NOLOCK) ON BKD_FKEY_BK_SEQ = BK_SEQ
AND DATEPART(YYYY,BKD_DATE_START) = DATEPART(YYYY,GETDATE())
AND DATEPART(MM,BKD_DATE_START) = DATEPART(MM,GETDATE())
AND DATEPART(DD,BKD_DATE_START) = DATEPART(DD,GETDATE())
AND BK_STATUS NOT IN ('CX','TP')
AND F_BOOK_HEADER.Deleted <> 1
AND F_BOOK_DATES.Deleted <> 1)),0)
/
sum(case when AllDayBooking = 1 then 1400 else
datediff(n,LO_TIME_START, LO_TIME_END) end) * 100),0),2) as PercentUtilised
from FAREALO with (NOLOCK)
inner join F_LO_TYPE with (NOLOCK) on LO_FKEY_LOT_SEQ = LOT_SEQ
where LO_BK_LOCATION = 1
and LOT_CBS = 1
Anybody see what I've missed?
Thanks
J

Here's the altered query which runs fine, after adding the MIN function:
select
round(COALESCE(
(COALESCE(MIN((select SUM((BKD_ADATE_ENDS - BKD_ADATE_START) * (60 * 24)) FROM F_BOOK_DATES
INNER JOIN F_BOOK_HEADER ON BKD_FKEY_BK_SEQ = BK_SEQ
and EXTRACT (YEAR from BKD_DATE_START ) = EXTRACT (YEAR from SYSDATE )
and EXTRACT (MONTH from BKD_DATE_START ) = EXTRACT (MONTH from SYSDATE )
and EXTRACT (DAY from BKD_DATE_START ) = EXTRACT (DAY from SYSDATE )
AND BK_STATUS NOT IN ('CX','TP')
AND F_BOOK_HEADER.Deleted <> 1
AND F_BOOK_DATES.Deleted <> 1)),9999999999.99,0)
/sum(case when AllDayBooking = 1 then 1400 else
((LO_TIME_END - LO_TIME_START) * (60 * 24)) end) * 100),0),2) as "PercentUtilised"
from FAREALO
inner join F_LO_TYPE on LO_FKEY_LOT_SEQ = LOT_SEQ
where LO_BK_LOCATION = 1
and LOT_CBS = 1;

Related

Hive query takes forever on Superset

I have a query that was written in Presto SQL format (100 lines of insert a query result to a table that already exists) and takes within 10 minutes to get the result.
Now I am going to use Airflow and need to change the query to Hive SQL format to append previous month's data, there is no error, but it is taking 75+ minutes now and the query is still running and not returning any result.
Shall I 'stop' it or is there anything else to consider?
SET hive.limit.query.max.table.partition = 1000000;
INSERT INTO TABLE schema.temp_tbl partition(year_month_key)
Select
distinct
tbl.account_id,
tbl.theme_status,
streaming.streaming_hours,
tbl.year_month as year_month_key
From
(
Select
tbl_0.year_month,
tbl_0.account_id,
case when max(tbl_0.theme_status) = 1 then 'With Theme' else 'No Theme' end as theme_status
From
(Select
streaming.year_month,
streaming.account_id,
case when theme_events.account_id is not null then 1 else 0 end as theme_status
from
(
Select
substring(date_key, 1, 7) as year_month,
last_day(add_months(date_key, -1)) as year_month_ed,
date_key,
upper(account_id) as account_id,
play_seconds
from agg_device_streaming_metrics_daily
Where date_key between date_add(last_day(add_months(current_date, -2)),1) and last_day(add_months(current_date, -1))
and play_seconds > 0
) streaming
left join
(
Select
upper(theme.virtualuserid) as account_id,
min(theme.createddate) as min_createddate,
min(theme.date_key) as date_key
From
(
select * from theme_activate_event_history
where date_key between '2019-01-01' and '2020-01-01'
and activate = 'true' and themetype in ('ThemeBundle','ScreenSaver','Skin','Audio')
union
select * from theme_activate_event_history
where date_key between '2020-01-01' and '2021-01-01'
and activate = 'true' and themetype in ('ThemeBundle','ScreenSaver','Skin','Audio')
union
select * from theme_activate_event_history
where date_key between '2021-01-01' and '2022-01-01'
and activate = 'true' and themetype in ('ThemeBundle','ScreenSaver','Skin','Audio')
union
select * from theme_activate_event_history
where date_key between cast('2022-01-01' as date) and last_day(add_months(current_date, -1))
and activate = 'true' and themetype in ('ThemeBundle','ScreenSaver','Skin','Audio')
) theme
group by theme.virtualuserid
) theme_events
on streaming.account_id = theme_events.account_id
and date(theme_events.date_key) <= date(streaming.year_month_ed)
) tbl_0
group by tbl_0.year_month, tbl_0.account_id
) tbl
inner join
(Select
substring(date_key, 1, 7) as year_month,
upper(account_id) as account_id,
cast(sum(play_seconds) / 3600 as double) as streaming_hours
from agg_device_streaming_metrics_daily
Where date_key between date_add(last_day(add_months(current_date, -2)),1) and last_day(add_months(current_date, -1))
and play_seconds > 0
group by substring(date_key, 1, 7), upper(account_id)
) streaming
on tbl.account_id = streaming.account_id and tbl.year_month = streaming.year_month;

Inserting multiple rows from a SELECT statement along with an array in another column

Hello when I run the below query:
SELECT fundid
FROM funds
WHERE reportingfrequency = 'Daily'
AND primarynavcostlocation = 'Wroclaw'
AND primaryaccountmgr1 = 'wx
I get:
"fundid"
11111
22222
So now what I'm trying to do is insert both those fundid rows along with an array so that the data will look something like below:
"fundid" | "listdate"
11111 | {2021-01-02, 2021-01-03}
22222 | {2021-01-02, 2021-01-03}
I've tried to finagle the query's around to get an insert working such as -
INSERT into nav_due_dates (fund_id, listdate)
VALUES(
(
SELECT fundid
FROM funds
WHERE reportingfrequency = 'Daily'
AND primarynavcostlocation = 'Wroclaw'
AND primaryaccountmgr1 = 'wxy'
),
(
SELECT array_agg(weekdays::date)
FROM generate_series(date'2021-01-01', date'2021-12-31', interval '1' day) as t(weekdays)
LEFT JOIN holidays.poland(2021, 2021) f ON (weekdays = f.datestamp)
WHERE f.datestamp IS NULL
AND extract(dow from weekdays) BETWEEN 1 AND 5
)
);
It returns:
ERROR: more than one row returned by a subquery used as an expression
and I've also tried the following after doing some digging -
INSERT INTO nav_due_dates (fund_id, listdate)
SELECT fundid
WHERE reportingfrequency = 'Daily'
AND primarynavcostlocation = 'Wroclaw'
AND primaryaccountmgr1 = 'wxy',
(
SELECT array_agg(weekdays::date)
FROM generate_series(date'2021-01-01', date'2021-12-31', interval '1' day) as t(weekdays)
LEFT JOIN holidays.poland(2021, 2021) f ON (weekdays = f.datestamp)
WHERE f.datestamp IS NULL
AND extract(dow from weekdays) BETWEEN 1 AND 5
)
FROM funds;
But the syntax errors I can't seem to resolve such as removing the , or the parenthesis around the array select statement that populates the listdate column.
I think you want to do this :
insert into nav_due_dates (fund_id, listdate)
select fundid, dd
from
(
SELECT fundid
FROM funds
WHERE reportingfrequency = 'Daily'
AND primarynavcostlocation = 'Wroclaw'
AND primaryaccountmgr1 = 'wxy'
) t1
cross join
(
SELECT array_agg(weekdays::date) dd
FROM generate_series(date'2021-01-01', date'2021-12-31', interval '1' day) as t(weekdays)
LEFT JOIN holidays.poland(2021, 2021) f ON (weekdays = f.datestamp)
WHERE f.datestamp IS NULL
AND extract(dow from weekdays) BETWEEN 1 AND 5
) t2
So I managed to get it working and it was entirely because of the ordering of the FROM section.
INSERT INTO nav_due_dates (fund_id, listdate)
SELECT fundid,
(
SELECT array_agg(weekdays::date)
FROM generate_series(date'2021-01-01', date'2021-12-31', interval '1' day) as t(weekdays)
LEFT JOIN holidays.poland(2021, 2021) f ON (weekdays = f.datestamp)
WHERE f.datestamp IS NULL
AND extract(dow from weekdays) BETWEEN 1 AND 5
)
FROM funds
WHERE reportingfrequency = 'Daily'
AND primarynavcostlocation = 'Wroclaw'
AND primaryaccountmgr1 = 'wxy';

how to use double group by and sum statements together in oracle

I am trying to use query below but it is giving an error
SELECT s.LOCAL_CODE,substr(p.ACCOUNT_CREDIT,-3),(p.SUMMA/100) as profit
FROM OPERATIONS s INNER JOIN LEADS p ON s.PAY_ID = p.PAY_ID
WHERE s.date_paid >= TO_DATE('03.12.2019', 'DD.MM.YYYY')
AND s.date_paid < TO_DATE('03.12.2019', 'DD.MM.YYYY') + INTERVAL '1' DAY
AND state = 'T'
AND s.filial_code = '006789'
AND SUBSTR(p.ACCOUNT_CREDIT, 1, 5) = '765294'
GROUP BY s.LOCAL_CODE,substr(p.ACCOUNT_CREDIT,-3);
If LEADS.SUMMA has expected value then you don't need Group By clause, else if you use Group By then all not grouped fields can be used only as arguments of aggregate functions:
SELECT s.LOCAL_CODE
, Substr(p.ACCOUNT_CREDIT, -3)
, Sum(p.SUMMA)/100 as profit
FROM OPERATIONS s
INNER JOIN LEADS p ON s.PAY_ID = p.PAY_ID
WHERE s.date_paid >= TO_DATE('03.12.2019', 'DD.MM.YYYY')
AND s.date_paid < TO_DATE('03.12.2019', 'DD.MM.YYYY') + INTERVAL '1' DAY
AND state = 'T'
AND s.filial_code = '006789'
AND SUBSTR(p.ACCOUNT_CREDIT, 1, 5) = '765294'
GROUP BY s.LOCAL_CODE
, substr(p.ACCOUNT_CREDIT, -3);

SQL Where Clause Maximo IBM

I want to create a where clause in Maximo.
We have a clause today where we can see the work order about to breach responded SLA.
But i want the clause to calculate to show work order about to breach responded SLA within 1 hour.
Is that possible?
Clause is as follows:
(woclass = 'WORKORDER' or woclass = 'ACTIVITY')
and historyflag = 0
and istask = 0
and workorderid in (select sla.ownerid from slarecords sla where sla.ownertable = 'WORKORDER' and sla.ownerid = workorderid)
and wonum not in (select wos.wonum from wostatus wos where wos.status = 'RESPONDED' and wos.siteid = siteid and wos.wonum = wonum)
and sysdate < targstartdate
and (((targstartdate - reportdate) - (targstartdate - sysdate))/(targstartdate - reportdate)*100)>90
and (siteid in (select defsite from maxuser mu where mu.sdx_siteteam is null and mu.userid = 'ALEXANDER.JEPPSON#SODEXO.COM' )
or (siteid in (select sis.siteid from sdx_integratedsites sis where sis.sdx_property = 'COMMANDCENTER' and sis.sdx_type = (select sdx_siteteam from maxuser mu where mu.userid = 'ALEXANDER.JEPPSON#SODEXO.COM' ))))
It sounds like you should change
and sysdate < targstartdate
to subtract an hour from the target
and sysdate < targstartdate - 1/24
or add an hour to the current time
and sysdate + 1/24 < targstartdate

How to find up similarly distributed control group for test group in sql?

The task is pretty ambitious. I have about 50k+ users in each month, and I want to match up similarly distributed with same size control group from the full pool of users, which about 50 mln users. To get similar distribution I have some categorical and numerical features. The categorical features will be just inner joined. Numerical features would to like to round up, but that makes the biggest problem.
Here is my code:
with pl_subs as( -- in the cte I
select al.*
,ROW_NUMBER() OVER(PARTITION BY
al.device_type
,al.report_mnth
,round(al.days_to_LAST_FLASH_DTTM, -1)
,round(al.LT_month, -1)
,round(al.REVC, -1)
,round(al.usg_in, -2)
,round(al.usg_AC, -1)
ORDER BY null) AS RN
from ai_pl_SUBS test_gr
inner join ai_SUBS_MONTH_CLR al
on al.cust_id = test_gr.cust_id
and al.report_mnth = test_gr.REGISTERED_mnth
where al.report_mnth = '2017-11' and test_gr.REGISTERED_mnth = '2017-11'
)
sel count(1) -- just to count from (
sel al.cust_id, pl_subs.rn rn_pl
,ROW_NUMBER() OVER(PARTITION BY
pl_subs.device_type
,pl_subs.report_mnth
,pl_subs.MCID
,round(pl_subs.days_to_LF, -1)
,round(pl_subs.LT_month, -1)
,round(pl_subs.REVC, -1)
,round(pl_subs.usg_in, -2)
,round(pl_subs.usg_AC, -1)
ORDER BY null) AS RN
from pl_subs
inner join ai_SUBS_MONTH_CLR al on
-- 2 categorilal features
pl_subs.device_type = al.device_type
and pl_subs.report_mnth = al.report_mnth
-- 5 numerical features
and round(pl_subs.days_to_LF, -1) = Round(al.days_to_LF, -1)
and round(pl_subs.LT_month, -1) = Round(al.LT_month, -1)
and round(pl_subs.REVC, -1) = Round(al.REVC, -1)
and round(pl_subs.usg_in, -2) = Round(al.usg_in, -2)
and round(pl_subs.usg_AC, -1) = Round(al.usg_AC, -1)
-- in the control group shouldnot be any cust_id from the test group
where al.cust_id not in (select cust_id from ai_pl_SUBS)
and al.report_mnth = '2017-11'
) _out where rn <= rn_pl
-- each 7 features determines strata. So I need to have so many cust as I have in appropriate strata in the test group
People in the test group have higher numerical values. In the code above I round up to tens, so intermediate spool wont be too big, but as I result only 36k users, not 50k as expected. I round up by 2 - the query will fail with spool problem
Similar distributed - have equal average for numerical values
Do I have any code mistakes? How the code can be modified to be possible the customer included to the strata multiple times?
My code above has some problems:
1) round(pl_subs.LT_month , -1) = Round(al.LT_month , -1) -- using rounds on widely distributed values will eventually cause problem on finding prober control client to test one. So just use cases:
case when LT_month <= 4 then '0'
when LT_month <= 8 then '1'
when LT_month <= 12 then '2'
when LT_month <= 17 then '3'
when LT_month <= 24 then '4'
when LT_month <= 36 then '5'
when LT_month <= 56 then '6'
when LT_month <= 83 then '7'
when LT_month <= 96 then '8'
Precomputing and using indexes will make the query to ran pretty fast. But don't overdo
2) CTE should contain only strata + the amount of people that group should to contain:
with pl_subs as( -- in the cte I
select
al.device_type
,al.report_mnth
-- rounds should be changed
,round(al.LT_month, -1)
,round(al.REVC, -1)
,round(al.usg_in, -2)
,round(al.usg_AC, -1)
, count(1) as rn
from ai_pl_SUBS test_gr
inner join ai_SUBS_MONTH_CLR al
on al.cust_id = test_gr.cust_id
and al.report_mnth = test_gr.REGISTERED_mnth
where al.report_mnth = '2017-11' and test_gr.REGISTERED_mnth = '2017-11'
group by 1
)
sel subs_id, report_mnth from (
sel al.subs_id, al.report_mnth, pl_subs.max_rn max_rn
,ROW_NUMBER() OVER(PARTITION BY
pl_subs.device_type
,pl_subs.report_mnth
,pl_subs.segment
ORDER BY null) AS RN
from pl_subs
inner join UAT_DM.ai_SUBS_MONTH_CLR al on
pl_subs.device_type = al.device_type
and pl_subs.report_mnth = al.report_mnth
and pl_subs.segment = al.segment
where al.subs_id not in (select subs_id from UAT_DM.ai_pl_SUBS)
and al.report_mnth = '2017-11'
) _out where rn <= max_rn;