I am trying to write an sql statement but i am getting syntax error. I know it is do with my select and case statement but cant figure out.As the error is not descriptive. I am using redshift
select school_district_teacher_ind,customer_status,initial_pay_type,(select(
CASE
WHEN total_line_price = 0
THEN 'free'
ELSE 'paid'
END
)
from storiacloud.schl_storia_revenue_fact_a)as a,count(distinct convert(varchar(100),[Otc_Order_Number])+'_'+ convert(varchar(100),[Otc_Order_Line_Number]))
from storiacloud.schl_storia_revenue_fact_a as fact
inner join
storiacloud.schl_storia_school_status as status
on fact.school_ucn = status.ucn
where date = '11/2/2015'
group by school_district_teacher_ind,customer_status,initial_pay_type,a
Below is the error
ERROR: Invalid Query:
Detail:
-----------------------------------------------
error: Invalid Query:
code: 8001
context: single-row subquery returns more than one row
query: 5132289
location: 25.cpp:69
process: padbmaster [pid=29183]
-----------------------------------------------
Execution time: 0.16s
1 statement failed.
The results that i expect are
Note first column customer type is school_district_teacher_ind in the above select statment
Your case was a subquery that is selecting from the same table as your main query. Try this;
SELECT school_district_teacher_ind ,
customer_status ,
initial_pay_type ,
CASE WHEN total_line_price = 0 THEN 'free'
ELSE 'paid'
END AS a ,
COUNT(DISTINCT CONVERT(VARCHAR(100), [Otc_Order_Number]) + '_'
+ CONVERT(VARCHAR(100), [Otc_Order_Line_Number]))
FROM storiacloud.schl_storia_revenue_fact_a AS fact
INNER JOIN storiacloud.schl_storia_school_status AS status ON fact.school_ucn = status.ucn
WHERE date = '11/2/2015'
GROUP BY school_district_teacher_ind ,
customer_status ,
initial_pay_type ,
CASE WHEN total_line_price = 0 THEN 'free'
ELSE 'paid'
END
I think you just want conditional aggregation. The query is something like this:
select school_district_teacher_ind, customer_status, initial_pay_type,
sum(case when total_line_price = 0 then 1 else 0 end) as free,
sum(case when total_line_price = 0 then 0 else 1 end) as paid
from storiacloud.schl_storia_revenue_fact_a fact inner join
storiacloud.schl_storia_school_status status
on fact.school_ucn = status.ucn
where date = '2015-11-02'
group by school_district_teacher_ind,customer_status, initial_pay_type;
Related
I am using SQL inside Oracle Cloud BI Publisher product, so I assume this is true SQL or PL/SQL. I am trying to satisfy the following condition: When a user selects accounting period 12 (December) I need the query to fetch all data for periods 12 and 13 (December and Adjustment, respectively). When I get a parenthesis, single quote combo, or nested Select statement which works; the selecting of the prompt (:p_month) of 12 results in an "invalid number" return. Changing the parenthesis, quote stuff other ways yields a direct error from the query when trying to save.
I have tried the following with the grouped result for the portion after THEN:
"invalid number" returns from prompt evaluation of statement passed:
('12''13')
('12,13')
(SELECT '12,13' from dual)
(SELECT "'12','13'" from dual)
"invalid identifier" from query direct:
(SELECT "12,13" from dual)
(SELECT "'12,13'" from dual)
"missing right parenthesis" from query direct:
(''12','13'')
('12','13')
The offending code line is directly below with the full code below that:
AND gl_periods.period_num IN (CASE WHEN (:p_month) = '12' THEN ('12','13') ELSE (:p_month) END)
SELECT
LPAD(gl_periods.period_num, 2,'0') AS period_num
,gl_periods.period_year AS period_year
,gl_code_combinations.segment1 AS segment1
,gl_code_combinations.segment2 AS segment2
,gl_code_combinations.segment3 AS segment3
,gl_code_combinations.segment4 AS segment4
,gl_code_combinations.segment5 AS segment5
,gl_code_combinations.segment6 AS segment6
,gl_code_combinations.segment7 AS segment7
,gl_ledgers.name AS ledger_name
,gl_ledgers.currency_code AS currency_code
,gl_balances.begin_balance_dr_beq AS begin_balance_dr
,gl_balances.begin_balance_cr_beq AS begin_balance_cr
,gl_balances.period_net_dr_beq AS activity_dr
,gl_balances.period_net_cr_beq AS activity_cr
,(SELECT DISTINCT
fnd_flex_values_vl.attribute1
FROM
fnd_flex_values_vl,
fnd_flex_value_sets
WHERE
1=1
AND fnd_flex_values_vl.flex_value = gl_code_combinations.segment2
AND fnd_flex_values_vl.flex_value_set_id = fnd_flex_value_sets.flex_value_set_id
AND fnd_flex_value_sets.flex_value_set_name = 'CostCenter XXX Enterprise') AS reporting_unit_code
,(SELECT DISTINCT
fnd_flex_values_vl.attribute7
FROM
fnd_flex_values_vl,
fnd_flex_value_sets
WHERE
1=1
AND fnd_flex_values_vl.flex_value = gl_code_combinations.segment2
AND fnd_flex_values_vl.flex_value_set_id = fnd_flex_value_sets.flex_value_set_id
AND fnd_flex_value_sets.flex_value_set_name = 'CostCenter XXX Enterprise') AS operating_country_code
,(SELECT DISTINCT
fnd_flex_values_vl.attribute6
FROM
fnd_flex_values_vl,
fnd_flex_value_sets
WHERE
1=1
AND fnd_flex_values_vl.flex_value = gl_code_combinations.segment2
AND fnd_flex_values_vl.flex_value_set_id = fnd_flex_value_sets.flex_value_set_id
AND fnd_flex_value_sets.flex_value_set_name = 'CostCenter XXX Enterprise') AS legal_country_code
FROM
gl_balances
INNER JOIN gl_code_combinations ON gl_balances.code_combination_id = gl_code_combinations.code_combination_id
INNER JOIN gl_ledgers ON gl_ledgers.ledger_id = gl_balances.ledger_id
INNER JOIN gl_periods ON gl_balances.period_name = gl_periods.period_name
WHERE
1=1
AND gl_balances.currency_code <> 'STAT'
AND gl_balances.actual_flag = 'A'
AND gl_periods.period_set_name = 'XXX Enterprise'
AND gl_code_combinations.account_type IN ('A','L','O')
AND (gl_balances.translated_flag IN ('N','R') OR gl_balances.translated_flag IS NULL)
AND (gl_ledgers.ledger_id IN (:p_ledger) OR LEAST (:p_ledger) IS NULL)
AND gl_periods.period_num IN (CASE WHEN (:p_month) = '12' THEN ('12','13') ELSE (:p_month) END)
AND (gl_periods.period_year IN (:p_year) OR LEAST (:p_year) IS NULL)
AND gl_ledgers.ledger_category_code = 'PRIMARY'
AND gl_ledgers.name NOT LIKE ('%SL%')
I was able to get the return I wanted with the following code snippet:
AND (
(gl_periods.period_num IN (CASE WHEN (:p_month) = '12' THEN '12' ELSE (:p_month) END))
OR
(gl_periods.period_num IN (CASE WHEN (:p_month) = '12' THEN '13' ELSE (:p_month) END))
)
If there is a more elegant answer, I would love to see it as I am always open to new ideas.
I am in the process of updating some SQL queries to run against MariaDB instead of via SQL Anywhere. One query I'm running is erroring with this:
Error Code: 1054. Unknown column 'choice' in 'field list'
That is for this query:
SELECT
(select firstname||' '||lastname||' ('||service||')' from staff_members where id_number = customer_assignment_reviews.staff_member_id) as Rep,
(select customer_firstname||' '|| customer_lastname from customers where id_number = customer_assignment_reviews.cs_id) as Cus,
last_modified as "Response Date",replace(review_reason,'’','') as "Reason",
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
FROM customer_assignment_reviews
where staff_member_id in (Select id_number from kar.staff_members where division_id = 6)
and "Response Date" between today() - 7 and today() /* Date Range */
and "Accepted?" = 'No'
Order by 3 desc
Is this error message as straightforward as it sounds? It's simply saying the column "choice" doesn't exist on the target table?
I'm just trying to reason through why this code (which I inherited) would be referencing a column that does not exist. Could something be expected here at runtime?
You don't need to use subquery in SELECT list
SELECT
-- ...
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
=>
SELECT
CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end as "Accepted?"
Additionaly syntax SELECT alias = expression is only T-SQL specific:
SELECT alias = 1
<=>
SELECT 1 AS alias
What is this supposed to mean?
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
Very importantly, a select is not needed here. You might mean:
(case when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as is_accepted -- prefer to not have to need escape characters
If accepted only takes those two values, you can simplify this to:
elt(accepted + 1, 'No', 'Yes') as is_accepted
This question already has an answer here:
How to use an Alias in a Calculation for Another Field
(1 answer)
Closed 3 years ago.
In my query below I am counting occurrences in a table based on the Status column. I also want to perform calculations based on the counts I am returning. For example, let's say I want to add 100 to the Snoozed value... how do I do this? Below is what I thought would do it:
SELECT
pu.ID Id, pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed,
Snoozed + 100 AS Test
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
I get this error:
Invalid column name 'Snoozed'.
How can I take the value of the previous SUM statement, add 100 to it, and return it as another column? What I was aiming for is an additional column labeled Test that has the Snooze count + 100.
You can't use one column to create another column in the same way that you are attempting. You have 2 options:
Do the full calculation (as #forpas has mentioned in the comments above)
Use a temp table or table variable to store the data, this way you can get the first 5 columns, and then you can add the last column or you can select from the temp table and do the last column calculations from there.
You can not use an alias as a column reference in the same query. The correct script is:
SELECT
pu.ID Id, pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END)+100 AS Snoozed
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
MSSQL does not allow you to reference fields (or aliases) in the SELECT statement from within the same SELECT statement.
To work around this:
Use a CTE. Define the columns you want to select from in the CTE, and then select from them outside the CTE.
;WITH OurCte AS (
SELECT
5 + 5 - 3 AS OurInitialValue
)
SELECT
OurInitialValue / 2 AS OurFinalValue
FROM OurCte
Use a temp table. This is very similar in functionality to using a CTE, however, it does have different performance implications.
SELECT
5 + 5 - 3 AS OurInitialValue
INTO #OurTempTable
SELECT
OurInitialValue / 2 AS OurFinalValue
FROM #OurTempTable
Use a subquery. This tends to be more difficult to read than the above. I'm not certain what the advantage is to this - maybe someone in the comments can enlighten me.
SELECT
5 + 5 - 3 AS OurInitialValue
FROM (
SELECT
OurInitialValue / 2 AS OurFinalValue
) OurSubquery
Embed your calculations. opinion warning This is really sloppy, and not a great approach as you end up having to duplicate code, and can easily throw columns out-of-sync if you update the calculation in one location and not the other.
SELECT
5 + 5 - 3 AS OurInitialValue
, (5 + 5 - 3) / 2 AS OurFinalValue
You can't use a column alias in the same select. The column alias do not precedence / sequence; they are all created after the eval of the select result, just before group by and order by.
You must repeat code :
SELECT
pu.ID Id,pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END)+ 100 AS Test
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
If you don't want to repeat the code, use a subquery
SELECT
ID, Name, LeadCount, Working, Uninterested,Converted, Snoozed, Snoozed +100 AS test
FROM
(SELECT
pu.ID Id,pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed
FROM Prospects p
INNER JOIN ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE p.Store = '108'
GROUP BY pu.Name, pu.Id) t
ORDER BY Name
or a view
I have a strange behaviour in report builder.
I'm working from an existing dataset and testing my own code in SQL studio before trying in report builder. And I'm lost because I don't understand why the following doesn't work :
SELECT
v_Collection_Alias.Name as CollectionName,
v_Package_Alias.Name as SoftwareName,
'Package' as ApplicationType,
NumberSuccessTable='NumberSuccessTable', sum(case when stat.LastState in (-1,13) then 1 else 0 end) as NumberSuccess,
NumberInProgressTable='NumberInProgress', sum(case when stat.LastState in (8,9) then 1 else 0 end) as NumberInProgress,
NumberUnknownTable='NumberUnknown', sum(case when stat.LastState in (0) then 1 else 0 end) as Unknown,
NumberErrorTable='NumberError', sum(case when stat.LastState in (11) then 1 else 0 end) as NumberError,
NumberOtherTable='NumberOther', sum(case when stat.LastState in (10) then 1 else 0 end) as NumberOther,
'' as LastModifiedby,
'' as Version,
v_Advertisement_Alias.CollectionID as CollectionID,
v_Advertisement_Alias.AdvertisementID as DeploymentID,
'' as CI_ID,
'' as DeploymentTime,
v_Advertisement_Alias.PresentTime as ModificationTime,
'' as AssignmentID
FROM fn_rbac_Advertisement(#UserSIDs) v_Advertisement_Alias
JOIN fn_rbac_ClientAdvertisementStatus(#UserSIDs) stat on v_Advertisement_Alias.AdvertisementID = stat.AdvertisementID
INNER JOIN fn_rbac_Package2(#UserSIDs) v_Package_Alias ON v_Advertisement_Alias.PackageID = v_Package_Alias.PackageID
INNER JOIN fn_rbac_Collection(#UserSIDs) v_Collection_Alias ON v_Advertisement_Alias.CollectionID = v_Collection_Alias.CollectionID
This in report builder is prompting me an error because fn_rbac_Advertisement.Name need a group by clause. Whereas the following is properly working in the original report :
SELECT
v_Collection_Alias.Name as CollectionName,
v_Package_Alias.Name as SoftwareName,
'' as ApplicationType,
'' as NumberSuccess,
'' as NumberInProgress,
'' as NumberUnknown,
'' as NumberErrors,
'' as NumberOther,
'' as LastModifiedby,
'' as Version,
v_Advertisement_Alias.CollectionID as CollectionID,
v_Advertisement_Alias.AdvertisementID as DeploymentID,
'' as CI_ID,
'' as DeploymentTime,
v_Advertisement_Alias.PresentTime as ModificationTime,
'' as AssignmentID,
'' as ApplicationType
FROM fn_rbac_Advertisement(#UserSIDs) v_Advertisement_Alias
INNER JOIN fn_rbac_Package2(#UserSIDs) v_Package_Alias ON v_Advertisement_Alias.PackageID = v_Package_Alias.PackageID
INNER JOIN fn_rbac_Collection(#UserSIDs) v_Collection_Alias ON v_Advertisement_Alias.CollectionID = v_Collection_Alias.CollectionID
and the following returns me what I want in SQL Studio :
Select
NumberSuccessTable='NumberSuccessTable', sum(case when stat.LastState in (-1,13) then 1 else 0 end),
NumberInProgressTable='NumberInProgress', sum(case when stat.LastState in (8,9) then 1 else 0 end),
NumberUnknownTable='NumberUnknown', sum(case when stat.LastState in (0) then 1 else 0 end) AS NumberU,
NumberErrorTable='NumberError', sum(case when stat.LastState in (11) then 1 else 0 end) AS NumberError,
NumberOtherTable='NumberOther', sum(case when stat.LastState in (10) then 1 else 0 end) as NumberOther
From v_ClientAdvertisementStatus stat
Thanks for any help guys ! :)
First Query:
when you use aggregate function like SUM you need to do a GROUP BY on all your columns that Don't have the aggregate function.
Second Query:
this works because you dont have an aggregate function in your select therefor you dont have to use GROUP BY and report builder can handle the sum and group by for you.
Third query:
this query works because you have aggregate function on all your columns so you dont need to GROUP BY.
Always remember the LOGICAL query processing order is as below:
1.FROM
2.WHERE
3.GROUP BY
4.HAVING
5.SELECT
6.ORDER BY
so your GROUP BY happens before SELECT for that reason when you group by you cant include '' in your group by clause because that column does not exists yet.
so it gives you an error.
When using aggregate functions (such as SUM) you must apply a GROUP BY clause to all columns that are not aggregated eg:
GROUP BY v_Collection_Alias.Name,
v_Package_Alias.Name,
v_Advertisement_Alias.CollectionID as CollectionID,
v_Advertisement_Alias.AdvertisementID as DeploymentID,
v_Advertisement_Alias.PresentTime as ModificationTime
Alternatively, if you don't want to maintain a lengthy GROUP BY clause you could remove the SUM functions from the SELECT statement and let the report handle the aggregation, with appropriate grouping in Report Builder.
I want to add some calculation inside my case statement to dynamically create the contents of a new column but I get the error:
Column 'Test1.qrank' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
This is the code I'm working on
case
when test1.TotalType = 'Average' then Test2.avgscore
when test1.TotalType = 'PercentOfTot' then (cnt/SUM(test1.qrank))
else cnt
end as displayscore
I did try to group but it didn't work.
Any hints?
The error you posted can happen when you're using a clause in the GROUP BY statement without including it in the select.
Example
This one works!
SELECT t.device,
SUM(case when transits.direction = 1 then 1 else 0 end) ,
SUM(case when transits.direction = 0 then 1 else 0 end) from t1 t
where t.device in ('A','B') group by t.device
This one not (omitted t.device from the select)
SELECT
SUM(case when transits.direction = 1 then 1 else 0 end) ,
SUM(case when transits.direction = 0 then 1 else 0 end) from t1 t
where t.device in ('A','B') group by t.device
This will produce your error complaining that I'm grouping for something that is not included in the select
Please, provide all the query to get more support.
You could use a Common Table Expression to create the SUM first, join it to the table, and then use the WHEN to to get the value from the CTE or the original table as necessary.
WITH PercentageOfTotal (Id, Percentage)
AS
(
SELECT Id, (cnt / SUM(AreaId)) FROM dbo.MyTable GROUP BY Id
)
SELECT
CASE
WHEN o.TotalType = 'Average' THEN r.avgscore
WHEN o.TotalType = 'PercentOfTot' THEN pt.Percentage
ELSE o.cnt
END AS [displayscore]
FROM PercentageOfTotal pt
JOIN dbo.MyTable t ON pt.Id = t.Id
If you're using SQL Server 2005 or above, you can use the windowing function SUM() OVER ().
case
when test1.TotalType = 'Average' then Test2.avgscore
when test1.TotalType = 'PercentOfTot' then (cnt/SUM(test1.qrank) over ())
else cnt
end as displayscore
But it'll be better if you show your full query to get context of what you actually need.