SQL grouping not working - sql

I am using MS SQL Server 2012
I have a query that uses a subquery to create a column that shows summed percent of assets. However I need that summed column to group by portfoliobasecode as shown below.
I have tried group by and Partition without success. With Group by the result is the portfolio codes correctly group but the summedpct is still the total of all portfolios and not subtotaling as I want.
With Partition I get the following error. I can use Top 1 but this does not give the desired result.
ERROR
Msg 512, Level 16, State 1, Line 17
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Using TOP 1
It may be I am placing group by or partition over in the wrong place in the query. I need a way to correctly group the column summedpct.
Here is the query:
https://dl.dropboxusercontent.com/u/29851290/cashpercent.sql
Here is the result set and desired result.
The problem with the actual result is it is taking the sum total of all PercentAssets and placing them in summedpct.
The result I want is these percent of assets grouped by portfoliobasecode. Note in the desired result set the summedpct of chambetr is 2.66 which is -457.50+460.18

You cannot use an "inline" query because it returns one row for each partition. So, you need a "join" I think. Perhaps this will work:
USE APXFIRM
--1. Establish the APX user session
DECLARE #SessionGUID nvarchar(70)
EXEC APXuser.pSessionInfoSetGuid #SessionGuid
--2. Execute the query against the Appraisal accounting function
DECLARE #ReportData varbinary(max)
EXEC APXUser.pAppraisal
-- Required Parameters. There may be other Optional Parameters.
#ReportData = #ReportData out,
#Portfolios = '#Test_Group',
#Date = '10/02/2013'
--3. Select the columns
SELECT
--Appraisal columns
a.MarketValue,
a.PercentAssets,
--Security Columns
s.SecuritySymbol,
s.SecurityTypeCode,
-- Portfolio Base columns
b.PortfolioBaseCode,
b.ReportHeading1,
bb.summedpct
--4. Join the Appraisal to additional views
FROM APXUser.fAppraisal (#ReportData) a
LEFT JOIN APXUser.vPortfolioBaseSettingEx b
ON b.PortfolioBaseID = a.PortfolioBaseID
LEFT JOIN APXUser.vSecurityVariant s
ON s.SecurityID = a.SecurityID
LEFT JOIN(
SELECT PortfolioBaseCode
, SUM(PercentAssets) as summedpct
FROM APXUser.fAppraisal (#ReportData) aa
LEFT JOIN APXUser.vPortfolioBaseSettingEx b
ON b.PortfolioBaseID = aa.PortfolioBaseID
LEFT JOIN APXUser.vSecurityVariant s
ON s.SecurityID = aa.SecurityID
WHERE s.SecTypeCode LIKe 'ca%'
AND s.SecTypeCode = aa.SecTypeCode
AND s.IsShort = aa.IsShortPosition
GROUP BY PortfolioBaseCode, SecurityTypeCode
) bb
on b.PortfolioBaseCode = bb.PortfolioBaseCode
WHERE s.SecTypeCode LIKe 'ca%'
AND s.SecTypeCode = a.SecTypeCode
AND s.IsShort = a.IsShortPosition
And summedpct >= #summedpct

Related

single-row subquery returns more than one row. Query not working with main query

I hve to display several cell values into one cell. So I am using this query:
select LISTAGG(fc.DESCRIPTION, ';'||chr(10))WITHIN GROUP (ORDER BY fc.SWITCH_NAME) AS DESCRIP from "ORS".SWITCH_OPERATIONS fc
group by fc.SWITCH_NAME
It is working fine. But when I am merging this with my main(complete) query then I am getting the error as: Error code 1427, SQL state 21000: ORA-01427: single-row subquery returns more than one row
Here is my complete query:
SELECT
TRACK_EVENT.LOCATION,
TRACK_EVENT.ELEMENT_NAME,
(select COUNT(*) from ORS.TRACK_EVENT b where (b.ELEMENT_NAME = sw.SWITCH_NAME)AND (b.ELEMENT_TYPE = 'SWITCH')AND (b.EVENT_TYPE = 'I')AND (b.ELEMENT_STATE = 'NORMAL' OR b.ELEMENT_STATE = 'REVERSE'))as COUNTER,
(select COUNT(*) from ORS.SWITCH_OPERATIONS fc where TRACK_EVENT.ELEMENT_NAME = fc.SWITCH_NAME and fc.NO_CORRESPONDENCE = 1 )as FAIL_COUNT,
(select MAX(cw.COMMAND_TIME) from ORS.SWITCH_OPERATIONS cw where ((TRACK_EVENT.ELEMENT_NAME = cw.SWITCH_NAME) and (cw.NO_CORRESPONDENCE = 1)) group by cw.SWITCH_NAME ) as FAILURE_DATE,
(select LISTAGG(fc.DESCRIPTION, ';'||chr(10))WITHIN GROUP (ORDER BY fc.SWITCH_NAME) AS DESCRIP from "ORS".SWITCH_OPERATIONS fc
group by fc.SWITCH_NAME)
FROM
ORS.SWITCH_OPERATIONS sw,
ORS.TRACK_EVENT TRACK_EVENT
WHERE
sw.SEQUENCE_ID = TRACK_EVENT.SEQUENCE_ID
Not only are subqueries in the SELECT list required to return exactly one row (or any time they're used for a singular comparison, like <, =, etc), but their use in that context tends to make the database execute them RBAR - Row-by-agonizing-row. That is, they're slower and consume more resources than they should.
Generally, unless the result set outside the subquery contains only a few rows, you want to construct subqueries as part of a table-reference. Ie, something like:
SELECT m.n, m.z, aliasForSomeTable.a, aliasForSomeTabe.bSum
FROM mainTable m
JOIN (SELECT a, SUM(b) AS bSum
FROM someTable
GROUP BY a) aliasForSomeTable
ON aliasForSomeTable.a = m.a
This benefits you in other ways to - it's easier to get multiple columns out of the same table-reference, for example.
Assuming that LISTAGG(...) can be included with other aggregate functions, you can change your query to look like this:
SELECT Track_Event.location, Track_Event.element_name,
Counted_Events.counter,
Failure.fail_count, Failure.failure_date, Failure.descrip
FROM ORS.Track_Event
JOIN ORS.Switch_Operations
ON Switch_Operations.sequence_id = Track_Event.sequence_id
LEFT JOIN (SELECT element_name, COUNT(*) AS counter
FROM ORS.Track_Event
WHERE element_type = 'SWITCH'
AND event_type = 'I'
AND element_state IN ('NORMAL', 'REVERSE')
GROUP BY element_name) Counted_Events
ON Counted_Events.element_name = Switch_Operations.swicth_name
LEFT JOIN (SELECT switch_name,
COUNT(CASE WHEN no_correspondence = 1 THEN '1' END) AS fail_count,
MAX(CASE WHEN no_correspondence = 1 THEN command_time END) AS failure_date,
LISTAGG(description, ';' || CHAR(10)) WITHIN GROUP (ORDER BY command_time) AS descrip
FROM ORS.Switch_Operations
GROUP BY switch_name) Failure
ON Failure.switch_name = Track_Event.element_name
This query was written to (attempt to) preserve the semantics of your original query. I'm not completely sure that's what you actually need but without sample starting data and desired results, I have no way to tell how else to improve this. For instance, I'm a little suspicious of the need of Switch_Operations in the outer query, and the fact that LISTAGG(...) is run over row where no_correspondence <> 1. I did change the ordering of LISTAGG(...), because the original column would not have done anything (because the order way the same as the grouping), so would not have been a stable sort.
Single-row subquery returns more than one row.
This error message is self descriptive.
Returned field can't have multiple values and your subquery returns more than one row.
In your complete query you specify fields to be returned. The last field expects single value from the subquery but gets multiple rows instead.
I have no clue about the data you're working with but either you have to ensure that subquery returns only one row or you have to redesign the wrapping query (possibly using joins when appropriate).

SSMS error: Subquery returned more than 1 value... but there is no subquery

The full error message is this one: Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. Everything I can find on it just says "yeah, just use TOP 1 and it'll be fine," only I don't even have a subquery or a select statement.
Here's the query:
update f
set f.new_monthnumber = datediff(mm, dateadd(dd, dbo.ufn_GetDaysInMonth(a.new_opendate) - 16, a.new_opendate), f.new_submit_date) + 1
from FilteredAccount a
left outer join FilteredNew_Financials f on f.new_name = a.accountnumber
where f.new_monthnumber is null
ufn_GetDaysInMonth is a user-defined function that analyzes the date passed to it and does not query the database at all, and in any case I've confirmed that it is not the cause of the error by running the query without it.
Anyone know what the heck is going on here?
Given that to write this query I would have swapped the tables and used an inner join, in order to have "FilteredNew_Financials" in both UPDATE and FROM clauses, pheraps there is a 1-to-n cardinality between the two tables on the join condition... maybe you have some dirty data in tables?
Are you sure "new_name" and "accountnumber" are primary and foreign keys (at least logically, if not structurally)?
I would have written the query slightly differenty:
update FilteredNew_Financials
set new_monthnumber = datediff(mm, dateadd(dd, dbo.ufn_GetDaysInMonth(a.new_opendate) - 16, a.new_opendate), f.new_submit_date) + 1
from FilteredAccount a
left outer join FilteredNew_Financials f on f.new_name = a.accountnumber
where f.new_monthnumber is null
Does that work?

Subselect a Summed col in Oracle

this is an attempted fix to a crystal reports use of 2 sub reports!
I have a query that joins 3 tables, and I wanted to use a pair of sub selects that bring in the same new table.
Here is the first of the two columns in script:
SELECT ea."LOC_ID", lo."DESCR", ea."PEGSTRIP", ea."ENTITY_OWNER"
, ea."PCT_OWNERSHIP", ea."BEG_BAL", ea."ADDITIONS", ea."DISPOSITIONS"
, ea."EXPLANATION", ea."END_BAL", ea."NUM_SHARES", ea."PAR_VALUE"
, ag."DESCR", ea."EOY", ea."FAKEPEGSTRIP",
(select sum(htb.END_FNC_CUR_US_GAAP)
from EQUITY_ACCOUNTS ea , HYPERION_TRIAL_BALANCE htb
where
htb.PEGSTRIP = ea.PEGSTRIP and
htb.PRD_NBR = 0 and
htb.LOC_ID = ea.LOC_ID and
htb.PRD_YY = ea.EOY
) firstHyp
FROM ("TAXPALL"."ACCOUNT_GROUPING" ag
INNER JOIN "TAXP"."EQUITY_ACCOUNTS" ea
ON (ag."ACCT_ID"=ea."PEGSTRIP") AND (ag."EOY"=ea."EOY"))
INNER JOIN "TAXP"."LOCATION" lo ON ea."LOC_ID"=lo."LOC_ID"
WHERE ea."EOY"=2009
ORDER BY ea."LOC_ID", ea."PEGSTRIP"
When this delivers the dataset the value of "firstHyp" fails to change by pegstrip value. It returns a single total for the join and fails to put the proper by value by pegstrip.
I thought that the where clause would have picked up the joins line by line.
I don't do Oracle syntax often so what am I missing here?
TIA
Your SQL is equivilent to the following:
SELECT ea."LOC_ID", lo."DESCR", ea."PEGSTRIP",
ea."ENTITY_OWNER" , ea."PCT_OWNERSHIP",
ea."BEG_BAL", ea."ADDITIONS", ea."DISPOSITIONS" ,
ea."EXPLANATION", ea."END_BAL", ea."NUM_SHARES",
ea."PAR_VALUE" , ag."DESCR", ea."EOY", ea."FAKEPEGSTRIP",
(select sum(htb.END_FNC_CUR_US_GAAP)
from EQUITY_ACCOUNTS iea
Join HYPERION_TRIAL_BALANCE htb
On htb.PEGSTRIP = iea.PEGSTRIP
and htb.LOC_ID = iea.LOC_ID
and htb.PRD_YY = iea.EOY
where htb.PRD_NBR = 0 ) firstHyp
FROM "TAXPALL"."ACCOUNT_GROUPING" ag
JOIN "TAXP"."EQUITY_ACCOUNTS" ea
ON ag."ACCT_ID"=ea."PEGSTRIP"
AND ag."EOY"=ea."EOY"
JOIN "TAXP"."LOCATION" lo
ON ea."LOC_ID"=lo."LOC_ID"
WHERE ea."EOY"=2009
ORDER BY ea."LOC_ID", ea."PEGSTRIP"
Notice that the subquery that generates firstHyp is not in any way dependant on the tables in the outer query... It is therefore not a Correllated SubQuery... meaning that the value it generates will NOT be different for each row in the outer query's resultset, it will be the same for every row. You need to somehow put something in the subquery that makes it dependant on the value of some row in the outer query so that it will become a correllated subquery and run over and over once for each outer row....
Also, you mention a pair of subselects, but I only see one. Where is the other one ?
Use:
SELECT ea.LOC_ID,
lo.DESCR,
ea.PEGSTRIP,
ea.ENTITY_OWNER,
ea.PCT_OWNERSHIP,
ea.BEG_BAL,
ea.ADDITIONS,
ea.DISPOSITIONS,
ea.EXPLANATION,
ea.END_BAL,
ea.NUM_SHARES,
ea.PAR_VALUE,
ag.DESCR,
ea.EOY,
ea.FAKEPEGSTRIP,
NVL(SUM(htb.END_FNC_CUR_US_GAAP), 0) AS firstHyp
FROM TAXPALL.ACCOUNT_GROUPING ag
JOIN TAXP.EQUITY_ACCOUNTS ea ON ea.PEGSTRIP = ag.ACCT_ID
AND ea.EOY = ag.EOY
AND ea.EOY = 2009
JOIN TAXP.LOCATION lo ON lo.LOC_ID = ea.LOC_ID
LEFT JOIN HYPERION_TRIAL_BALANCE htb ON htb.PEGSTRIP = ea.PEGSTRIP
AND htb.LOC_ID = ea.LOC_ID
AND htb.PRD_YY = ea.EOY
AND htb.PRD_NBR = 0
GROUP BY ea.LOC_ID,
lo.DESCR,
ea.PEGSTRIP,
ea.ENTITY_OWNER,
ea.PCT_OWNERSHIP,
ea.BEG_BAL,
ea.ADDITIONS,
ea.DISPOSITIONS,
ea.EXPLANATION,
ea.END_BAL,
ea.NUM_SHARES,
ea.PAR_VALUE,
ag.DESCR,
ea.EOY,
ea.FAKEPEGSTRIP,
ORDER BY ea.LOC_ID, ea.PEGSTRIP
I agree with Charles Bretana's assessment that the original SELECT in the SELECT clause was not correlated, which is why the value never changed per row. But the sub SELECT used the EQUITY_ACCOUNTS table, which is the basis for the main query. So I removed the join, and incorporated the HYPERION_TRIAL_BALANCE table into the main query, using a LEFT JOIN. I wrapped the SUM in an NVL rather than COALESCE because I didn't catch what version of Oracle this is for.

MAX Subquery in SQL Anywhere Returning Error

In sqlanywhere 12 I wrote the following query which returns two rows of data:
SELECT "eDatabase"."Vendor"."VEN_CompanyName", "eDatabase"."OrderingInfo"."ORD_Timestamp"
FROM "eDatabase"."OrderingInfo"
JOIN "eDatabase"."Vendor"
ON "eDatabase"."OrderingInfo"."ORD_VEN_FK" = "eDatabase"."Vendor"."VEN_PK"
WHERE ORD_INV_FK='7853' AND ORD_DefaultSupplier = 1
Which returns:
'**United Natural Foods IN','2018-02-07 15:05:15.513'
'Flora ','2018-02-07 14:40:07.491'
I would like to only return the row with the maximum timestamp in the column "ORD_Timestamp". After simply trying to select by MAX("eDatabase"."OrderingInfo"."ORD_Timestamp") I found a number of posts describing how that method doesn't work and to use a subquery to obtain the results.
I'm having difficulty creating the subquery in a way that works and with the following query I'm getting a syntax error on my last "ON":
SELECT "eDatabase"."Vendor"."VEN_CompanyName", "eDatabase"."OrderingInfo"."ORD_Timestamp"
FROM ( "eDatabase"."OrderingInfo"
JOIN
"eDatabase"."OrderingInfo"
ON "eDatabase"."Vendor"."VEN_PK" = "eDatabase"."OrderingInfo"."ORD_VEN_FK" )
INNER JOIN
(SELECT "eDatabase"."Vendor"."VEN_CompanyName", MAX("eDatabase"."OrderingInfo"."ORD_Timestamp")
FROM "eDatabase"."OrderingInfo")
ON "eDatabase"."Vendor"."VEN_PK" = "eDatabase"."OrderingInfo"."ORD_VEN_FK"
WHERE ORD_INV_FK='7853' AND ORD_DefaultSupplier = 1
Does anyone know how I can adjust this to make the query correctly select only the max ORD_Timestamp row?
try this:
SELECT TOP 1 "eDatabase"."Vendor"."VEN_CompanyName", "eDatabase"."OrderingInfo"."ORD_Timestamp"
FROM "eDatabase"."OrderingInfo"
JOIN "eDatabase"."Vendor"
ON "eDatabase"."OrderingInfo"."ORD_VEN_FK" = "eDatabase"."Vendor"."VEN_PK"
WHERE ORD_INV_FK='7853' AND ORD_DefaultSupplier = 1
order by "ORD_Timestamp" desc
this orders them biggest on to and say only hsow the top row

SQL function returning a error regarding a subquery

Good morning all,
I am trying to make a revenue view, but I am stuck due to a error I cannot fix.
I've made a function which calcutates total revenue from both Accessories and Bikes. The function combines these to give a result per month, which is the variable. I tried the seperate queries and they seem to work properly. The following occurs, I seem to be missing a step I think:
CREATE FUNCTION fnOmzetPMaand
(
#Maand AS int
)
RETURNS int
AS
BEGIN
DECLARE #AccOmzet AS int
SET #AccOmzet = (
SELECT dbo.fnOmzet(SUM(a.Accessoire_Dagprijs), h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum)
FROM Huurovereenkomst h
INNER JOIN HuurovereenkomstAccessoire ha
ON ha.HuurovereenkomstAccessoire_Huurovereenkomst_id = h.Huurovereenkomst_id
INNER JOIN Accessoire a
ON a.Accessoire_id = ha.HuurovereenkomstAccessoire_Accessoire_id
WHERE MONTH(h.Huurovereenkomst_Betaal_datum) = #Maand
GROUP BY h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum
)
DECLARE #FietsOmzet AS int
SET #FietsOmzet = (
SELECT dbo.fnOmzet(SUM(f.Fiets_Dagprijs), h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum)
FROM Huurovereenkomst h
INNER JOIN HuurovereenkomstFiets hf
ON hf.HuurovereenkomstFiets_Huurovereenkomst_id = h.Huurovereenkomst_id
INNER JOIN Fiets f
ON f.Fiets_id = hf.HuurovereenkomstFiets_Fiets_id
WHERE MONTH(h.Huurovereenkomst_Betaal_datum) = #Maand
GROUP BY h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum
)
RETURN #FietsOmzet + #AccOmzet
END
The view:
CREATE VIEW vOmzetPMaand
AS
SELECT DATENAME(MONTH, Huurovereenkomst_Betaal_datum) Maand,
dbo.fnOmzetPMaand(MONTH(Huurovereenkomst_Betaal_datum)) Omzet
FROM Huurovereenkomst
The error:
Msg 512, Level 16, State 1, Line 43
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as an
expression.
The expected results:
May 100
June 200
July 150
etc etc.
USE [Biker]
GO
/****** Object: UserDefinedFunction [dbo].[fnOmzet] Script Date: 05-Jan-18 12:05:50 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[fnOmzet]
(
#Bedrag AS int,
#BeginDatum AS DATETIME,
#EindDatum AS DATETIME
)
RETURNS int
AS
BEGIN
RETURN #Bedrag * DATEDIFF(Y, #BeginDatum, #EindDatum)
END
Yo have two subqueries but both are using the same table and grouped by the same criteria.
Without looking at your dataset, I would said that since the expected result is aggregated by month (based on your question): The impacting data is very likely that you have more than one combination of "h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum" per month. If that is the case, and since those columns values are grouped but not aggregated they would be returning multiple rows.
The following are some of the options that I can think of so far:
Option 1. Use aggregated functions on both of those fields like min and max (if the business logic allows for it in order to obtain a single record.
Option 2. Handling the multiple rows of each result and guarantee a single resultant value. (this can be accomplish with multiple solutions that could be from extra sub query withing your select statement, to even return the values on a table alike structure like table variable and then do an extra processing to return only the final value over the multiple rows)
Option 3. Extract somehow the relevant month from the combination "h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum" and group by the month instead of the you current grouping.
Important: I would prefer the option #3 or some variation of it if the business rules allows it.