Error in my sql query - sql

Hey guys i am trying to run this query in my postgres db but it returns an error: [Err] ERROR: syntax error at or near ","
LINE 13: and not substr(a.zoneiddest , 1 ,3) = any ('254','255','256'...
The query is like this
SELECT
to_char(a.CALLDATE, 'yyyymm') AS month,
min(a.calldate) AS start_time,
max(a.calldate) AS end_time,
ceil(SUM(a.CALLDURATION::INT) / 60) AS minutes,
COUNT(DISTINCT a.IDENTIFIANT) AS distinct_callers,
a.zoneiddest AS country_code,
b.country
FROM cdr_data a,
country_codes b
WHERE a.CALLSUBCLASS = '002'
AND a.CALLCLASS = '008'
AND a.zoneiddest::INT > 0
AND SUBSTR(a.CALLEDNUMBER, 1, 2) NOT IN
( '77', '78', '75', '70', '71', '41', '31', '39', '76', '79' )
AND NOT substr(a.zoneiddest, 1, 3) = ANY
( '254', '255','256', '211', '257', '250', '256' )
AND trim(a.zoneiddest) = trim(b.country_code)
GROUP BY
to_char(a.CALLDATE, 'yyyymm'),
a.zoneiddest,
b.country
ORDER BY 1
This same query works well in oracle with just a small minor change on a.zoneiddest::integer > 0 to just a.zoneiddest > 0
What could i be doing wrong

The problem is with your ANY operator. If i understand your query correctly, you can just substitute it with a NOT IN statement.
SELECT to_char (a.CALLDATE,'yyyymm') as month,min(a.calldate) as
start_time,max(a.calldate) as end_time,
ceil(SUM (a.CALLDURATION::integer) / 60) AS minutes,
COUNT (DISTINCT a.IDENTIFIANT) AS distinct_callers,
a.zoneiddest as country_code,b.country
FROM cdr_data a,COUNTRY_CODES b
WHERE a.CALLSUBCLASS = '002'
AND a.CALLCLASS = '008'
and a.zoneiddest::integer > 0
AND SUBSTR (a.CALLEDNUMBER, 1, 2) NOT IN
('77', '78', '75', '70', '71', '41', '31', '39', '76','79')
// This line
AND substr(a.zoneiddest , 1 ,3) NOT IN
('254','255','256','211','257','250','256')
// End of line
and trim(a.zoneiddest) = trim(b.country_code)
GROUP BY to_char (a.CALLDATE,'yyyymm') ,a.zoneiddest,b.country
ORDER BY 1

Try using keyword any combine with parameter array like this:
= any (ARRAY['254','255','256','211','257','250','256'])

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;

Why I get error Invalid number ORA-01722:

I am a little bit confusing and have no idea how to solve this problem. I have column in table Quantity which store Time value.
I want to create a following story. If I have for example
Quantity
8:00
8:00
It needs to SUM() this two and in output I need to get 16 HOURS
Second think, it needs to take last two number :00 and add to HOURS.
This is what I do so far
SELECT
(SUM(SUBSTR(A.Quantity, ':', 1)) + TRUNC((SUM(SUBSTR(A.Quantity, ':', -1)) / 60),0)), ':' ,
MOD(SUM(SUBSTR(A.Quantity, ':' , -1)), 60)
AS TOTAL_SUM FROM (
SELECT
ata.ATAID AS AtaId, ata.ProjectID, ata.StartDate, ataAW.Quantity
FROM
ata
INNER JOIN
weekly_report
ON
weekly_report.ataId = ata.ATAID
INNER JOIN
ata_articles ataAW
ON
ataAW.wrId = weekly_report.id
WHERE
ata.ATAID = 10987
AND
ataAW.type = 1
OR
ataAW.type = 2
OR
ataAW.type = 3
AND
(weekly_report.status != 3 AND weekly_report.status != 4)
AND
(
weekly_report.year < (SELECT year FROM weekly_report WHERE id = 89)
OR
(
weekly_report.year <= (SELECT year FROM weekly_report WHERE id = 89)
AND
weekly_report.week <= (SELECT week FROM weekly_report WHERE id = 89)
)
)
) A
group by A.AtaId
So far better explanation, when I run first part of query I need to get something like
SELECT
CONCAT(
-- extract hours froAm time and add minutes converted to hours
(SUM(SUBSTRING_INDEX(aa.Quantity, ':', 1)) + TRUNCATE((SUM(SUBSTRING_INDEX(aa.Quantity, ':', -1)) / 60),0))
-- , ':',
-- extract minutes from time and find reminder (modulo)*/
-- LPAD((SUM(SUBSTRING_INDEX(aa.Quantity, ':', -1)) % 60), 2, 0)
) AS W_TOTAL_SUM
FROM
ata_articles aa
INNER JOIN
weekly_report wr
ON
aa.wrId = wr.id
WHERE
aa.wrId = 69
AND
aa.type = 1
TOTAL_SUM
16
And when I run second part
SELECT
CONCAT(
-- extract hours froAm time and add minutes converted to hours
-- (SUM(SUBSTRING_INDEX(aa.Quantity, ':', 1)) + TRUNCATE((SUM(SUBSTRING_INDEX(aa.Quantity, ':', -1)) / 60),0))
-- , ':',
-- extract minutes from time and find reminder (modulo)*/
LPAD((SUM(SUBSTRING_INDEX(aa.Quantity, ':', -1)) % 60), 2, 0)
) AS W_TOTAL_SUM
FROM
ata_articles aa
INNER JOIN
weekly_report wr
ON
aa.wrId = wr.id
WHERE
aa.wrId = 69
AND
aa.type = 1
I get output
TOTAL_SUM
00
Can someone guide me and tell me how to solve this issue since I try every solution but unfortunetlly doesn't work. And here is what I try so far, but I always get message
ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number
SELECT
(SUM(SUBSTR(A.Quantity, ':', 1)) + TRUNC((SUM(SUBSTR(A.Quantity, ':', -1)) / 60),0)), ':' ,
MOD(SUM(SUBSTR(A.Quantity, ':' , -1)), 60)
AS TOTAL_SUM FROM (
SELECT
ata.ATAID AS AtaId, ata.ProjectID, ata.StartDate, ataAW.Quantity
FROM
ata
INNER JOIN
weekly_report
ON
weekly_report.ataId = ata.ATAID
INNER JOIN
ata_articles ataAW
ON
ataAW.wrId = weekly_report.id
WHERE
ata.ATAID = 10987
AND
ataAW.type = 1
OR
ataAW.type = 2
OR
ataAW.type = 3
AND
(weekly_report.status != 3 AND weekly_report.status != 4)
AND
(
weekly_report.year < (SELECT year FROM weekly_report WHERE id = 89)
OR
(
weekly_report.year <= (SELECT year FROM weekly_report WHERE id = 89)
AND
weekly_report.week <= (SELECT week FROM weekly_report WHERE id = 89)
)
)
) A
group by A.AtaId
UPDATE
I get output error message
ORA-00907: missing right parenthesis
00907. 00000 - "missing right parenthesis"
*Cause:
*Action:
Error at Line: 267 Column: 19
SELECT ( EXTRACT( DAY FROM duration ) * 24 + EXTRACT( HOUR FROM duration ) )
|| ':'
|| TO_CHAR( EXTRACT( MINUTE FROM DURATION ), 'FM00' )
|| ' HOURS' AS duration
FROM (
SELECT NUMTODSINTERVAL(SUM( SUBSTR( quantity, 1, INSTR( quantity, ':' ) - 1 ) ),'HOUR')
+ NUMTODSINTERVAL(SUM( SUBSTR( quantity, INSTR( quantity, ':' ) + 1 ) ), 'MINUTE' )
AS duration
FROM (
SELECT ata.ATAID AS AtaId, ata.ProjectID, ata.StartDate, ataAW.Quantity
FROM ata
INNER JOIN weekly_report
ON weekly_report.ataId = ata.ATAID
INNER JOIN ata_articles ataAW
ON ataAW.wrId = weekly_report.id
INNER JOIN (SELECT week, year FROM weekly_report WHERE id = 89 ) b
ON ( weekly_report.year < b.year OR ( weekly_report.year = b.year AND weekly_report.week <= b.week ))
WHERE ata.ATAID = 10987
AND ataAW.type IN ( 1, 2, 3 )
AND weekly_report.status NOT IN ( 3, 4 )
))
group by A.AtaId
Here is what I get as output when I execute following code
DURATION
:HOURS
If you have the (slightly more complicated) sample data:
CREATE TABLE table_name ( Quantity ) AS
SELECT '8:00' FROM DUAL UNION ALL
SELECT '7:30' FROM DUAL UNION ALL
SELECT '0:30' FROM DUAL;
Then you can use string functions to get the hour and minute parts and sum those and then convert the totals to an interval (so you don't end up with 15:60 HOURS) and then format the output:
SELECT ( EXTRACT( DAY FROM duration ) * 24
+ EXTRACT( HOUR FROM duration )
)
|| ':'
|| TO_CHAR( EXTRACT( MINUTE FROM DURATION ), 'FM00' )
|| ' HOURS' AS duration
FROM (
SELECT NUMTODSINTERVAL(
SUM( SUBSTR( quantity, 1, INSTR( quantity, ':' ) - 1 ) ),
'HOUR'
)
+
NUMTODSINTERVAL(
SUM( SUBSTR( quantity, INSTR( quantity, ':' ) + 1 ) ),
'MINUTE'
) AS duration
FROM table_name
);
Which outputs:
| DURATION |
| :---------- |
| 16:00 HOURS |
db<>fiddle here

Oracle - Display 'No Rows' when query returns no results

I would like my Oracle SQL output to display 'No Rows Found' when the query returns no results.
I am trying to use the NVL function but Im getting an error stating
'ERROR at line 21: ORA-00907: missing right parenthesis'
SELECT NVL((
SELECT TO_CHAR(CHGDATE, 'yyyy-mm')
,CHGFIELD
,DBNAME
,COUNT(*)
FROM APPCHANGEHIST A
,DATABASEFIELD D
WHERE A.CHGFIELD = D.FIELDNUM
AND trunc(CHGDATE) BETWEEN add_months(to_date(to_char((sysdate - to_char(sysdate, 'dd') + 1), 'dd-mon-yyyy')), - 1)
AND to_date(to_char((sysdate - to_char(sysdate, 'dd')), 'dd-mon-yyyy'))
AND CHGFIELD = 79
AND OLDVALUE IS NOT NULL
AND EXISTS (
SELECT 1
FROM USERPROF
WHERE USERID = A.CHGREQUESTOR
)
GROUP BY TO_CHAR(CHGDATE, 'yyyy-mm')
,CHGFIELD
,DBNAME
ORDER BY 1
,4 DESC
), "No Rows");
I don't have issues when I run this statement alone without the NVL
SELECT TO_CHAR(CHGDATE, 'yyyy-mm')
,CHGFIELD
,DBNAME
,COUNT(*)
FROM APPCHANGEHIST A
,DATABASEFIELD D
WHERE A.CHGFIELD = D.FIELDNUM
AND trunc(CHGDATE) BETWEEN add_months(to_date(to_char((sysdate - to_char(sysdate, 'dd') + 1), 'dd-mon-yyyy')), - 1)
AND to_date(to_char((sysdate - to_char(sysdate, 'dd')), 'dd-mon-yyyy'))
AND CHGFIELD = 79
AND OLDVALUE IS NOT NULL
AND EXISTS (
SELECT 1
FROM USERPROF
WHERE USERID = A.CHGREQUESTOR
)
GROUP BY TO_CHAR(CHGDATE, 'yyyy-mm')
,CHGFIELD
,DBNAME
ORDER BY 1
,4 DESC
Ok, at a high level, you can use the following pattern:
WITH results AS
(
SELECT *
FROM dual d
WHERE d.dummy = 'Y'
)
SELECT *
FROM results
UNION ALL
SELECT 'No Rows Found'
FROM dual
WHERE NOT EXISTS (SELECT 'X'
FROM results);
You can play with this by changing the value in the WITH clause between 'X' and 'Y'.
In your query, you would just replace the SELECT within the WITH clause with your query.

Putting 2 queries together

How can I put these two queries together? I know the magic is in the joins.
SELECT tblCanisterNew.CountyOperatorID
,tblCanisterNew.Year
,Sum(Nz([value])) AS RevenueMiles
,0 AS TotalExpenses
FROM tblCanisterNew
WHERE (
((tblCanisterNew.typeID) = 4)
AND (
(CLng([elementkey])) IN (6021, 6022, 60, 23, 6024, 6025))
)
GROUP BY tblCanisterNew.CountyOperatorID
,tblCanisterNew.Year
UNION
SELECT tblCanisterNew.CountyOperatorID
,tblCanisterNew.Year
,0 AS RevenueMiles
,Sum(Nz([value])) AS TotalExpenses
FROM tblCanisterNew
WHERE (
((tblCanisterNew.typeID) = 4)
AND (
(CLng([elementkey])) IN (1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014))
)
GROUP BY tblCanisterNew.CountyOperatorID
,tblCanisterNew.Year;
You can do conditional aggregation :
SELECT tc.CountyOperatorID, tc.Year,
Sum(CASE WHEN CLng([elementkey]) IN (6021,6022,60,23,6024,6025) THEN VALUE ELSE 0 END) AS RevenueMiles,
Sum(CASE WHEN CLng([elementkey]) IN (1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014) THEN VALUE ELSE 0 END) AS TotalExpenses
FROM tblCanisterNew tc
WHERE tc.typeID = 4
GROUP BY tc.CountyOperatorID, tc.Year;
Note : SQL Server doesn't' have CLng(), equivalent function would be convert(bigint, elementkey). But, as per data you don't need to do conversation.

How to get missing values in date range?

I have table with following structure:
And I'm trying to get grouped values between two dates, problem is, that i would like to have also retuned rows for dates which are not in select, for example i have range for
WHERE m.date BETWEEN "2014-09-02" AND "2014-09-10"
But for example in date 2014-09-06 is no related row in table, so in result should be
2014-09-06| 0 | 0 | 0 | 0
How can i do it please? (if is it possible with SQLLite database).
Here is the query which i'm using:
SELECT substr(m.date, 1, 10) as my_date, COUNT(m.ID) AS 'NUMBER_OF_ALL_CALLS',
(SELECT COUNT(*) FROM dialed_calls subq WHERE subq.call_result = 'DONE'
AND substr(m.date, 1, 10) = substr(subq.DATE, 1, 10)) as 'RESULT_DONE',
(SELECT COUNT(*) FROM dialed_calls subq WHERE subq.call_result = 'NOT_INTERESTED'
AND substr(m.date, 1, 10) = substr(subq.DATE, 1, 10)) as 'RESULT_NOT_INTERESTED',
(SELECT COUNT(*) FROM dialed_calls subq WHERE subq.call_result = 'NO_APPOINTMENT'
AND substr(m.date, 1, 10) = substr(subq.DATE, 1, 10)) as 'RESULT_NO_APP'
FROM dialed_calls m
WHERE m.date BETWEEN "2014-09-02" AND "2014-09-05"
GROUP BY my_date
Many thanks for any help.
Table structure:
BEGIN TRANSACTION;
CREATE TABLE dialed_calls(Id integer PRIMARY KEY,
'date' datetime,
'called_number' VARCHAR(45),
'call_result' VARCHAR(45),
'call_duration' INT,
'synced' BOOL);
/* Create few records in this table */
INSERT INTO dialed_calls VALUES(1,'2014-09-02 15:54:34+0200',
'800123456', 'NOT_INTERESTED', 10, 0);
INSERT INTO dialed_calls VALUES(2,'2014-09-02 15:56:30+0200',
'800123456', 'NO_APPOINTMENT', 10, 0);
INSERT INTO dialed_calls VALUES(3,'2014-09-02 16:01:49+0200',
'800123456', 'DONE', 9, 0);
INSERT INTO dialed_calls VALUES(4,'2014-09-02 16:03:03+0200',
'800123456', 'NO_APPOINTMENT', 69, 0);
INSERT INTO dialed_calls VALUES(5,'2014-09-02 18:09:34+0200',
'800123456', 'NO_APPOINTMENT', 3, 0);
INSERT INTO dialed_calls VALUES(6,'2014-09-02 18:54:02+0200',
'123456789', 'NO_APPOINTMENT', 89, 0);
INSERT INTO dialed_calls VALUES(7,'2014-09-02 18:55:25+0200',
'123456789', 'NOT_INTERESTED', 89, 0);
INSERT INTO dialed_calls VALUES(8,'2014-09-03 18:36:58+0200',
'123456789', 'DONE', 185, 0);
INSERT INTO dialed_calls VALUES(9,'2014-09-04 18:36:58+0200',
'123456789', 'DONE', 185, 0);
INSERT INTO dialed_calls VALUES(10,'2014-09-05 18:36:58+0200',
'123456789', 'DONE', 185, 0);
COMMIT;
Try this:
SELECT
d.date AS DATE,
IFNULL(NUMBER_OF_ALL_CALLS, 0) AS NUMBER_OF_ALL_CALLS,
IFNULL(RESULT_DONE, 0) AS RESULT_DONE,
IFNULL(RESULT_NOT_INTERESTED, 0) AS RESULT_NOT_INTERESTED,
IFNULL(RESULT_NO_APP, 0) AS RESULT_NO_APP
FROM
(SELECT DATE('1970-01-01', '+' || (t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) || ' days') date FROM
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) d
LEFT JOIN
(
SELECT substr(m.date, 1, 10) as my_date, COUNT(m.ID) AS 'NUMBER_OF_ALL_CALLS',
(SELECT COUNT(*) FROM dialed_calls subq WHERE subq.call_result = 'DONE'
AND substr(m.date, 1, 10) = substr(subq.DATE, 1, 10)) as 'RESULT_DONE',
(SELECT COUNT(*) FROM dialed_calls subq WHERE subq.call_result = 'NOT_INTERESTED'
AND substr(m.date, 1, 10) = substr(subq.DATE, 1, 10)) as 'RESULT_NOT_INTERESTED',
(SELECT COUNT(*) FROM dialed_calls subq WHERE subq.call_result = 'NO_APPOINTMENT'
AND substr(m.date, 1, 10) = substr(subq.DATE, 1, 10)) as 'RESULT_NO_APP'
FROM dialed_calls m
GROUP BY my_date
) t
ON d.date = t.my_date
WHERE d.date BETWEEN '2014-09-02' AND '2014-09-10'
ORDER BY d.date;
Above query will first the retrieve the dates between the specified date range and later will join the retrieved values with your table.
This is a good case for joining to a Calendar table.
http://web.archive.org/web/20070611150639/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html
Note this is a SQL server link, but you can adapt this to SQLlite.
You could do your calculations, and then right join the results to the calendar table, so that the dates appear with NULL values. Or you could COALESCE() the nulls to something that makes more sense, like 0.
to get intermediate dates as the query result you need a table with all the dates in the range.
in some rdbms you can populate a temporary table to join with.
you will have to compare the date part only (without time).
be careful with your between because the second date has time 00:00:00 and maybe it's not what you meant.