double select in SQL query - sql

Writing a code with two select statements in big query. Not sure why its not recognizing the fields. Getting error Field --> 'd3.fiscal_week_begin_date' not found; did you mean 'fiscal_week_begin_date'?
SELECT
*
FROM
[acquisition.acquisition_program_cost_summary] as test,
(
SELECT
d.fiscal_week_begin_date AS fiscal_week_begin_date,
d.fiscal_week_end_date AS fiscal_week_end_date
FROM
datamart.date_dim as d
WHERE
d.week_of_fiscal_year =30) as d3
WHERE
test.created_timestamp >= d3.fiscal_week_begin_date
AND test.created_timestamp <= d3.fiscal_week_end_date;

In BigQuery comma (,) does not represent JOIN but rather UNION ALL
So, most likely you meant to do JOIN like below
Please note you should switch to BigQuery Standard SQL
SELECT *
FROM acquisition.acquisition_program_cost_summary as test
JOIN (
SELECT
d.fiscal_week_begin_date AS fiscal_week_begin_date,
d.fiscal_week_end_date AS fiscal_week_end_date
FROM datamart.date_dim as d
WHERE d.week_of_fiscal_year = 30
) as d3
ON test.created_timestamp >= d3.fiscal_week_begin_date
AND test.created_timestamp <= d3.fiscal_week_end_date

Related

SQL CASE WHEN ELSE not working in AWS Athena

I have the script below setup in AWS Athena, the goal is to replace some budget numbers (total) with 0 if they are within a certain category (costitemid). I'm getting the following error in AWS Athena and could use some advice as to why it isn't working. Is the problem that I need to repeat everything in the FROM and GROUP BY in the WHEN and ELSE? Code below the error. Thank you!
SYNTAX_ERROR: line 6:9: 'projectbudgets.projectid' must be an aggregate expression or appear in GROUP BY clause
This query ran against the "acorn-prod-reports" database, unless qualified by the query. Please post the error message on our forum or contact customer support with Query Id: 077f007b-61a0-4f6b-aa1f-dd38bb401218
SELECT
CASE
WHEN projectbudgetlineitems.costitemid IN (462561,462562,462563,462564,462565,462566,478030) THEN (
SELECT
projectbudgets.projectid
, projectbudgetyears.year fiscalYear
, projectbudgetyears.status
, "sum"(((0 * projectbudgetlineitems.unitcost) * (projectbudgetlineitems.costshare * 1E-2))) total
)
ELSE (
SELECT
projectbudgets.projectid
, projectbudgetyears.year fiscalYear
, projectbudgetyears.status
, "sum"(((projectbudgetlineitems.quantity * projectbudgetlineitems.unitcost) * (projectbudgetlineitems.costshare * 1E-2))) total
)
END
FROM
(("acorn-prod-etl".target_acorn_prod_acorn_projectbudgets projectbudgets
INNER JOIN "acorn-prod-etl".target_acorn_prod_acorn_projectbudgetyears projectbudgetyears ON (projectbudgets.id = projectbudgetyears.projectbudgetid))
INNER JOIN "acorn-prod-etl".target_acorn_prod_acorn_projectbudgetlineitems projectbudgetlineitems ON (projectbudgetyears.id = projectbudgetlineitems.projectbudgetyearid))
--WHERE (((projectbudgetlineitems.costitemid <> 478030) AND (projectbudgetlineitems.costitemid < 462561)) OR (projectbudgetlineitems.costitemid > 462566))
GROUP BY projectbudgets.projectid, projectbudgetyears.year, projectbudgetyears.status
Your syntax is wrong (at least according to most SQL dialects.) You can't generally say "SELECT CASE WHEN (condition) THEN (this select clause) ELSE (that select clause) END FROM (tables)"
You can only use CASE to calculate a single value.
But it looks as if the only change between your two inner SELECT clauses is whether you use 0 or the quantity in the final multiplication. And that is perfect for a CASE!
I do not guarantee this will work right off the bat, because I don't have your setup or an idea of your table layout. However, it's a step in the right direction:
SELECT
projectbudgets.projectid
, projectbudgetyears.year fiscalYear
, projectbudgetyears.status
, "sum"(
((
CASE
WHEN projectbudgetlineitems.costitemid IN (462561,462562,462563,462564,462565,462566,478030)
THEN 0
ELSE projectbudgetlineitems.quantity
END * projectbudgetlineitems.unitcost
) * (
projectbudgetlineitems.costshare * 1E-2
))) total
FROM
(("acorn-prod-etl".target_acorn_prod_acorn_projectbudgets projectbudgets
INNER JOIN
"acorn-prod-etl".target_acorn_prod_acorn_projectbudgetyears projectbudgetyears
ON (projectbudgets.id = projectbudgetyears.projectbudgetid))
INNER JOIN "acorn-prod-etl".target_acorn_prod_acorn_projectbudgetlineitems projectbudgetlineitems
ON (projectbudgetyears.id = projectbudgetlineitems.projectbudgetyearid))
GROUP BY
projectbudgets.projectid, projectbudgetyears.year, projectbudgetyears.status
This could solve your problem if you want to sum the items for each project and year and status except for certain line items. Here, it is correct to use a "where" condition and not "case when" :
SELECT
projectbudgets.projectid,
projectbudgetyears.year,
projectbudgetyears.status,
"sum"(((projectbudgetlineitems.quantity * projectbudgetlineitems.unitcost) *
(projectbudgetlineitems.costshare * 1E-2))) total
FROM
(("acorn-prod-etl".target_acorn_prod_acorn_projectbudgets projectbudgets
INNER JOIN "acorn-prod-etl".target_acorn_prod_acorn_projectbudgetyears
projectbudgetyears ON (projectbudgets.id = projectbudgetyears.projectbudgetid))
INNER JOIN "acorn-prod-etl".target_acorn_prod_acorn_projectbudgetlineitems
projectbudgetlineitems ON (projectbudgetyears.id =
projectbudgetlineitems.projectbudgetyearid))
WHERE projectbudgetlineitems.costitemid NOT IN
(462561,462562,462563,462564,462565,462566,478030)
GROUP BY projectbudgets.projectid, projectbudgetyears.year,
projectbudgetyears.status
;

Parsing with substring returning wrong value

I have this query which tries to capture the last 11 characters excluding the semi colon at the end of the date(string). But when I run the script it returns value which is not included in the string, and im stuck for days.
Here's my query
select TOP 2 a.ACCOUNT,a.GPSDATE,
SUBSTRING(b.smsmsg, LEN(b.smsmsg) - 10, 6) [KM2]
from TblGPSCur a
inner join GPRSIN b on a.ACCOUNT = b.SMSFR
where exists(select * from GPRSIN b where b.SMSFR = a.ACCOUNT
and b.smsdt between '2014-10-27 14:00:00' and '2014-10-27 14:49:54')
THE RESULT IS THIS
This is the top 2 data im trying to parse
The result should be 277511767.8
Can anyone tell me where I might be doing wrong on this one?
You can use RIGHT() function of SQL like this -
SELECT TOP 2 a.ACCOUNT
,a.GPSDATE
RIGHT(b.smsmsg, 11) [KM2]
FROM TblGPSCur a
INNER JOIN GPRSIN b ON a.ACCOUNT = b.SMSFR
WHERE EXISTS (
SELECT *
FROM GPRSIN b
WHERE b.SMSFR = a.ACCOUNT
AND b.smsdt BETWEEN '2014-10-27 14:00:00'
AND '2014-10-27 14:49:54'
)
You have your SUBSTRING() setup incorrectly, it should be:
SELECT SUBSTRING(b.smsmsg, LEN(b.smsmsg) - 11, 11)
As the starting position is LEN(x) - 11, and you want 11 characters after that point.
Alternately, you can use LEFT() and RIGHT():
declare #SillyLongString as nvarchar(100)
set #SillyLongString = '1234567890a;s.a.dpoiuytghjkmnbvfg,277511767.8;'
select left(right(#SillyLongString, 12),11)
-- outputs: 277511767.8
This selects the 12 right-most characters and then takes the first 11 characters from that string.
Adding to your query:
select TOP 2 a.ACCOUNT,a.GPSDATE,
left(right(b.smsmsg, 12),11) [KM2] ...

SQL Server : connect by level for DATE type with union

I've found basic answer for replacing the Oracle's "CONNECT BY LEVEL" in this question but my case is little bit more complicated:
Basically things that I want to replace looks like this:
...
UNION ALL
Select
adate, 'ROAD' as TSERV_ID, 0 AS EQ_NBR
from
(SELECT
to_date(sysdate - 732,'dd/mm/yy') + rownum -1 as adate, rownum
FROM
(select rownum
from dual
connect by level <= 732)
WHERE rownum <= 732)
UNION ALL
Select
adate, 'PORTPACK' as TSERV_ID, 0 AS EQ_NBR
from
(SELECT
to_date(sysdate - 732,'dd/mm/yy') + rownum -1 as adate, rownum
FROM
(select rownum from dual connect by level <= 732)
WHERE rownum <= 732)
UNION ALL
....
Now, the single dual connect is easy, even if this is apparently not very efficient method
WITH CTE AS (
SELECT dateadd(day,-720,CONVERT (date, GETDATE())) as Datelist
UNION ALL
SELECT dateadd(day,1,Datelist)
FROM CTE
WHERE datelist < getdate() )
SELECT *,'ROAD' as Tserv_ID , 0 as EQ_NBR FROM CTE
option (maxrecursion 0)
repeating the union is hard because I get an error:
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
There are more parts of this union that I've provided here; I've tried to use the "WITH" only at start but no luck. Am I missing something obvious here?
EDIT: There is of course big question WHY I am even trying to do such thing: Personally, I wouldn't, but at the other end of the query there is a huge Crystal Report that runs once every month and which accepts data in this particular format. End of the FULL query's output is something like
3 columns of data
3 Columns of data
...
Currentdate-732,"ROAD",0
Currentdate -731,"ROAD",0
...
Currentdate, "ROAD,"0"
Currentdate -732, "PORTPAK", 0
Currentdate -731, "PORTPAK", 0
etc.
Are you trying to do:
WITH CTE1 AS (...),
CTE2 AS (...)
SELECT stuff FROM CTE1
UNION ALL
SELECT stuff FROM CTE2;
? This is a common challenge, I guess it is not very discoverable that in order to use more than one CTE, you just separate them with a comma.
That all said, it seems like you are just trying to generate a series of dates. A recursive CTE (never mind a series of many of them) is not the most efficient way to do this. Instead of telling us you want to replace CONNECT BY LEVEL and showing us the syntax you've tried, why don't you just show or describe the output you want? We've already got an appreciation that you've tried something on your own (thanks!) but we'd rather give you an efficient solution than bridging the gap to an inefficient one.
As an example, here is something that requires a lot less redundant code, and ( think gives you what you're after:
DECLARE #n INT = 722, #d DATE = CURRENT_TIMESTAMP;
;WITH v AS (SELECT v FROM (VALUES('ROAD'),('PORTPACK')) AS v(v)),
n AS (SELECT TOP (#n) n = ROW_NUMBER() OVER (ORDER BY number)
FROM master.dbo.spt_values ORDER BY n)
SELECT Datelist = DATEADD(DAY, 2-n.n, #d), Tserv_ID = v.v, EQ_NBR = 0
FROM n CROSS JOIN v
ORDER BY Tserv_ID, Datelist;

Yield Return equivalent in SQL Server

I am writing down a view in SQL server (DWH) and the use case pseudo code is:
-- Do some calculation and generate #Temp1
-- ... contains other selects
-- Select statement 1
SELECT * FROM Foo
JOIN #Temp1 tmp on tmp.ID = Foo.ID
WHERE Foo.Deleted = 1
-- Do some calculation and generate #Temp2
-- ... contains other selects
-- Select statement 2
SELECT * FROM Foo
JOIN #Temp2 tmp on tmp.ID = Foo.ID
WHERE Foo.Deleted = 1
The result of the view should be:
Select Statement 1
UNION
Select Statement 2
The intended behavior is the same as the yield returnin C#. Is there a way to tell the view which SELECT statements are actually part of the result and which are not? since the small calculations preceding what I need also contain selects.
Thank you!
Yield return in C# returns rows one at a time as they appear in some underlying function. This concept does not exist in SQL statements. SQl is set-based, returning the entire result set, conceptually as a unit. (That said, sometimes queries run slowly and you will see rows returned slowly or in batches.)
You can control the number of rows being returns using TOP (in SQL Server). You can select particular rows to be returned using WHERE statements. However, you cannot specify a UNION statement that conditionally returns rows from some components but not others.
The closest you may be able to come is something like:
if UseTable1Only = 'Y'
select *
from Table1
else if UseTable2Only = 'Y'
select *
from Table2
else
select *
from table1
union
select *
from table2
You can do something similar using dynamic SQL, by constructing the statement as a string and then executing it.
I found a better work around. It might be helpful for someone else. It is actually to include all the calculation inside WITH statements instead of doing them in the view core:
WITH Temp1 (ID)
AS
(
-- Do some calculation and generate #Temp1
-- ... contains other selects
)
, Temp2 (ID)
AS
(
-- Do some calculation and generate #Temp2
-- ... contains other selects
)
-- Select statement 1
SELECT * FROM Foo
JOIN Temp1 tmp on tmp.ID = Foo.ID
WHERE Foo.Deleted = 1
UNION
-- Select statement 2
SELECT * FROM Foo
JOIN Temp2 tmp on tmp.ID = Foo.ID
WHERE Foo.Deleted = 1
The result will be of course the UNION of all the outiside SELECT statements.

How to filter MySQL SELECT by an aggregate function?

SELECT h11, HA11
FROM florin.h11
WHERE (3>d1 AND 3<d2) OR (3>d1 AND 3=d2 AND id=MAX(id))
UNION (3=d1 AND 3<d2 AND id=MIN(id));
Here a screenshot of my table stucture:
I think what you would like to do is something like this:
SELECT h11, HA11
FROM florin.h11
WHERE (3>d1 AND 3<d2)
OR (3>d1 AND 3=d2 AND id = (SELECT MAX(t2.id)
FROM florin.h11 AS t2))
OR (3=d1 AND 3<d2 AND id = (SELECT MIN(t3.id)
FROM florin.h11 AS t3));
First wrong thing is
Please mention if, florin is database and h11 is table.
If florin is table then write only "select h11,HA11 from florin", don't write column name.
Second wrong thing is
Union operator is used to join results of two query. For more info surf www.w3school.com
So, fire query like
select h11, HA11
from florin
where (3 > d1 and 3 < d2) or (3 > d1 and 3 = d2 and id = MAX(id))
union
select h11, HA11
from florin
where (3 = d1 and 3 < d2 and id = MIN(id))
Here may this query doesn't return desired result but this was my imagine that you want such type of query.