A problem in returning a table with Null On it - sql

i want my function to return a A table with some values
I must fix something in the update but i don't know what
this is the function FngetTableH BELOW
ALTER FUNCTION [dbo].[FnGetTableH]
(
#Date DateTime
)
RETURNS #Listeab_ Table(CLOSING_PRICE money,IdValeur int)
AS
BEGIN
Insert #Listeab_
( CLOSING_PRICE ,IdValeur)
select Distinct 0 , IdValeur
From Historique
Update #Listeab_
Set CLOSING_PRICE = (Select CLOSING_PRICE
from Historique H
inner join (Select MAX(#Date) As DATEDU,IdValeur FROM Historique
where
DATE_NEGO<= #Date
group by IdValeur ) L2
on
H.DATE_NEGO=L2.DATEDU
and
H.IdValeur=L2.IdValeur
)
return
END
when i Execute this code
declare #Date date = '10/09/2013'
---select*from FnGetTableH(#Date)
select C.IdClient,H.IdValeur,C.RaisonSocial,SUM( case I.sens
WHEN 'c' then + I.Qantite
WHEN'd' then - I.Qantite
END) as 'Solde', H.closing_price
from Imputations I
Inner join FnGetTableH(#Date) H
on H.IdValeur=I.IdValeur
Inner join Clients C
on C.IdClient=I.IdClient
where I.DateImputation=#Date
group by C.IdClient,RaisonSocial,H.closing_price,H.IdValeur
Order by IdClient asc
i get
Msg 512, Niveau 16, État 1, Ligne 4
La sous-requête a retourné plusieurs valeurs. Cela n'est pas autorisé quand la sous-requête suit =, !=, <, <= , >, >= ou quand elle est utilisée en tant qu'expression.
L'instruction a été arrêtée.

In your innermost query I think MAX(#Date) should be MAX(DATE_NEGO), which might explain why the closing price query is returning multiple results.
There is still the possibility of multiple results, so you might need to account for that You could select max(closing_price) if it doesn't matter which, though I suspect it might, in which case you need to do some ordering to select the correct price to use.
EDIT: Try this:
ALTER FUNCTION [dbo].[FnGetTableH]
(
#Date DATETIME
)
RETURNS #Listeab_ TABLE
(
CLOSING_PRICE MONEY,
IdValeur INT
)
AS
BEGIN
WITH prices AS
(
SELECT IdValeur,
CLOSING_PRICE,
ROW_NUMBER() OVER (PARTITION BY IdValuer ORDER BY DATE_NEGO DESC) rn
FROM Historique
WHERE DATE_NEGO <= #Date
)
INSERT #Listeab_(CLOSING_PRICE, IdValeur)
SELECT DISTINCT ISNULL(p.CLOSING_PRICE, 0),
h.IdValeur
FROM Historique h
LEFT OUTER JOIN prices p ON h.IdValeur = p.IdValeur
AND p.rn = 1
RETURN;
END;

your query "Select CLOSING_PRICE from Historique H inner..." may be returning more than 1 value.

Use top to select 1 record. May be it will solve your error.
select Distinct 0 , IdValeur
From Historique
Update #Listeab_
Set CLOSING_PRICE = (Select Top 1 CLOSING_PRICE
from Historique H
inner join (Select MAX(#Date) As DATEDU,IdValeur FROM Historique
where
DATE_NEGO<= #Date
group by IdValeur ) L2
on
H.DATE_NEGO=L2.DATEDU and H.IdValeur=L2.IdValeur
)

Related

Subquery returned more than 1 value. My WHERE clause needs to remove SELECT statements

I have a SQL Stored Procedure that is giving issues. I am aware that it is most likely the SELECT statements in the WHERE clause that are returning multiple values. I commented out the WHERE and results were returned.
My question is how do I modify the statement so that I can still filter on those conditions?
Stored Proc code:
SELECT
REPORT_SPOOL.ID,
REPORT_SPOOL.REPORT_SPOOL_TYPE_ID,
REPORT_SPOOL.FUND_ID,
REPORT_SPOOL.PERF_ENTITY_ID,
REPORT_SPOOL.REPORT_GUID,
REPORT_SPOOL.REPORT_TEMPLATE_GUID,
PERF_ENTITY.CODE AS PERF_ENTITY_CODE,
PERF_ENTITY.NAME AS PERF_ENTITY_NAME,
FUND.CODE AS FUND_CODE,
FUND.NAME AS FUND_NAME,
REPORT.CODE AS REPORT_CODE,
REPORT.NAME AS REPORT_NAME,
REPORT_TEMPLATE.CODE AS REPORT_TEMPLATE_CODE,
REPORT_TEMPLATE.NAME AS REPORT_TEMPLATE_NAME,
FUND.ACCOUNTING_START AS START_DATE,
FUND.ACCOUNTING_END AS END_DATE
FROM
PERF_ENTITY
RIGHT OUTER JOIN
REPORT
INNER JOIN
REPORT_SPOOL
ON REPORT.GUID = REPORT_SPOOL.REPORT_GUID
INNER JOIN
REPORT_TEMPLATE
ON REPORT_SPOOL.REPORT_TEMPLATE_GUID = REPORT_TEMPLATE.GUID
ON PERF_ENTITY.ID = REPORT_SPOOL.PERF_ENTITY_ID
LEFT OUTER JOIN
FUND
ON REPORT_SPOOL.FUND_ID = FUND.ID
WHERE
(END_DATE IS NULL OR END_DATE > #REPORT_DATE)
AND
REPORT_SPOOL.FUND_ID = (SELECT FUND_ID FROM FUND_HLD WHERE [DATE] = #REPORT_DATE)
AND
REPORT_SPOOL.FUND_ID = (SELECT FUND_ID FROM FUND_TRD_LINE_VIEW WHERE [DATE] >= (SELECT DATEFROMPARTS(YEAR(#REPORT_DATE),MONTH(#REPORT_DATE),1)) AND [DATE] <= #REPORT_DATE)
Those last 2 SELECTS are the issue
Replace = with in in the sub query:
REPORT_SPOOL.FUND_ID in (SELECT FUND_ID FROM FUND_HLD WHERE [DATE] = #REPORT_DATE)
AND
REPORT_SPOOL.FUND_ID in (SELECT FUND_ID FROM FUND_TRD_LINE_VIEW WHERE [DATE] >= (SELECT DATEFROMPARTS(YEAR(#REPORT_DATE),MONTH(#REPORT_DATE),1)) AND [DATE] <= #REPORT_DATE)

SQL conundrum - date filter doesn't work

Really scratching my head here. I have a query that has a date filter. However, I keep getting results that lie outside my date filter period! I have checked that my column is indeed a date column, I have tried using Between and >= <= and none of these seem to have the slightest impact.
Here is an example of my code.
Declare #PARAM_REPORTING_START_DATE as datetime
Declare #PARAM_REPORTING_END_DATE as datetime
Declare #PARAM_CRDTR_ID as integer
Set #PARAM_REPORTING_START_DATE = '2015/06/12'-- 05:39:44 AM'
Set #PARAM_REPORTING_END_DATE = '2015/06/24'-- 05:39:44 AM'
Set #PARAM_CRDTR_ID = 1005
--select #PARAM_REPORTING_START_DATE, #PARAM_REPORTING_END_DATE
Select distinct
capj.cnsmr_accnt_pymnt_jrnl_id,
c.cnsmr_nm_prfx_txt,
c.cnsmr_nm_frst_txt,
c.cnsmr_nm_lst_txt,
capj.cnsmr_accnt_pymnt_pstd_dt,
isdate(capj.cnsmr_accnt_pymnt_pstd_dt) as is_date,
capj.bckt_trnsctn_typ_cd as capj_bckt_trnsctn_typ_cd ,
pm.pymnt_memo_nm
from
cnsmr_accnt_pymnt_jrnl capj
inner join cnsmr_pymnt_jrnl cpj
on capj.cnsmr_pymnt_jrnl_id = cpj.cnsmr_pymnt_jrnl_id
inner join pymnt_memo pm
on pm.pymnt_memo_id = cpj.pymnt_memo_id
inner join crdtr cr
on capj.crdtr_id = cr.crdtr_id
inner join cnsmr_accnt ca
on ca.cnsmr_accnt_id = capj.cnsmr_accnt_id
inner join cnsmr c on c.cnsmr_id = ca.cnsmr_id
Where
capj.cnsmr_accnt_pymnt_pstd_dt>=#PARAM_REPORTING_START_DATE
and
capj.cnsmr_accnt_pymnt_pstd_dt<=#PARAM_REPORTING_END_DATE
and
( -1 IN ( #PARAM_CRDTR_ID ) ) OR ( cr.crdtr_ID in (#PARAM_CRDTR_ID) )
There is a misplacement of braces
Where
capj.cnsmr_accnt_pymnt_pstd_dt>=#PARAM_REPORTING_START_DATE
and
capj.cnsmr_accnt_pymnt_pstd_dt<=#PARAM_REPORTING_END_DATE
and
( -1 IN ( #PARAM_CRDTR_ID ) OR cr.crdtr_ID in (#PARAM_CRDTR_ID) )
You will get all results that satisfy
OR ( cr.crdtr_ID in (#PARAM_CRDTR_ID) )
so the date filter doesn't matter.
You should rearrange the the brackets/braces in your WHERE clause, e.g.
WHERE
capj.cnsmr_accnt_pymnt_pstd_dt
BETWEEN #PARAM_REPORTING_START_DATE AND #PARAM_REPORTING_END_DATE
AND
(
#PARAM_CRDTR_ID = -1
OR
#PARAM_CRDTR_ID = cr.crdtr_ID
);

Using results of JOIN statement to join on the results of another JOIN statement

I have the following 2 Join Statements:
--Get Total Hrs
DECLARE #BeginDate datetime, #EndDate datetime
set #BeginDate = '01-01-2013'
set #EndDate = '12-31-2013'
BEGIN
SELECT F.Type, E.Product, SUM(F.Hours * E.Amount) AS 'Total Hours'
FROM Hours H
INNER JOIN Equipment E
ON F.SN = E.SN
WHERE (F.Date BETWEEN #BeginDate AND #EndDate)
GROUP BY F.Type, E.Product
ORDER BY Product ASC
END
--Get Number of Unscheduled Removals
DECLARE #BeginDate1 datetime, #EndDate1 datetime
set #BeginDate1 = '01-01-2013'
set #EndDate1 = '12-31-2013'
BEGIN
SELECT LEFT(dbo.fn_GetPartName(R.PartID),CHARINDEX('-',dbo.fn_GetPartName(R.PartID), 1) - 1) AS 'Part No',
Count(s.status) AS NumberUnscheduledRemovals
FROM Repair R
INNER JOIN Conversion C
ON R.Performed = C.Performed
AND R.Confirmed = C.Confirmed
INNER JOIN Status S
ON C.StatusID = S.StatusID
WHERE (R.Received BETWEEN #BeginDate1 AND #EndDate1)
AND (S.Status = 'UNSCHEDULED')
GROUP BY LEFT(dbo.fn_GetPartName(R.PartID),CHARINDEX('-',dbo.fn_GetPartName(R.PartID), 1) - 1)
ORDER BY LEFT(dbo.fn_GetPartName(R.PartID),CHARINDEX('-',dbo.fn_GetPartName(R.PartID), 1) - 1) ASC
END
Both queries have results including part numbers (these have the same values). I want to INNER JOIN the results from both queries on the resulting part numbers. have been trying for a while but cant seem to get the syntax right to do it.
Use a temp table using CREATE TABLE #TempPartNum1 & #TempPartNum2.
Grab all the relevant data from the first two queries and put them in the temp tables, then join the temp tables.
You could also use a CTE ("Common Table Expression"):
;WITH QueryOne AS (
... put your first query here
), QueryTwo AS (
... put your second query here
) SELECT blah blah blah
FROM QueryOne INNER JOIN QueryTwo ON foo = bar
CTEs are very handy for things like this.

SQL add Sum to existing query (Cannot perform an aggregate function on an expression containing an aggregate or a subquery.)

I have a existing working SQL query I would like to now GroupBy but am getting the error: Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Explanation of my scenario:
My main table (dbo.DataLog) contains 3 columns, TimestampUTC, MeterTagId, Data.
Data typically comes in at 15 minute intervals and I have many meters (MeterTagId) for each
TimestampUTC. The Data column is a float and this is a totalised value. i.e. to get the actual value for a meter period I need to subtract the last value from the current one. Before now I have successfully been querying individual meters but now I am trying to group by time and show a sum/total of all meters for that time.
Original working non summed query:
SELECT
l.TimestampUTC
-- Get this value minus the last value
,(SELECT (l.[Data] -
( SELECT TOP 1 l2.Data
FROM [DataLog] l2
WHERE l2.MeterTagId = l.MeterTagId
AND l2.TimestampUTC < l.TimestampUTC
ORDER BY l2.TimestampUTC DESC)
)
) AS Actual_Value
FROM [dbo].[DataLog] l
INNER JOIN [dbo].MeterTags t on t.MeterTagId = l.MeterTagId
INNER JOIN [dbo].Meters m on m.MeterId = t.MeterId
INNER JOIN [dbo].GroupsMeters gm on gm.MeterId = m.MeterId
INNER JOIN [dbo].Groups g on g.GroupId = gm.GroupId
LEFT OUTER JOIN dbo.Units u on u.UnitId = t.UnitId
WHERE (#MeterId is null OR M.MeterId in (#MeterId))
AND (#MeterTagId is null OR t.MeterTagId in (#MeterTagId))
AND (#StartDate is null OR l.TimestampUTC >= #StartDate)
AND (#EndDate is null OR l.TimestampUTC <= #EndDate)
AND (#GroupId is null OR g.GroupId in (#GroupId))
.
My attempt to to get the summary:
SELECT
l.TimestampUTC
-- Get this value minus the last value
, (SELECT SUM(l.[Data] -
( SELECT TOP 1 l2.Data
FROM [DataLog] l2
WHERE l2.MeterTagId = l.MeterTagId
AND l2.TimestampUTC < l.TimestampUTC
ORDER BY l2.TimestampUTC DESC)
)
)AS Actual_Value
FROM [dbo].[DataLog] l
INNER JOIN [dbo].MeterTags t on t.MeterTagId = l.MeterTagId
INNER JOIN [dbo].Meters m on m.MeterId = t.MeterId
INNER JOIN [dbo].GroupsMeters gm on gm.MeterId = m.MeterId
INNER JOIN [dbo].Groups g on g.GroupId = gm.GroupId
LEFT OUTER JOIN dbo.Units u on u.UnitId = t.UnitId
WHERE (#MeterId is null OR M.MeterId in (#MeterId))
AND (#MeterTagId is null OR t.MeterTagId in (#MeterTagId))
AND (#StartDate is null OR l.TimestampUTC >= #StartDate)
AND (#EndDate is null OR l.TimestampUTC <= #EndDate)
AND (#GroupId is null OR g.GroupId in (#GroupId))
AND t.Name ='Real Energy Net'
GROUP BY l.TimestampUTC
I have read other posts on here but can't get my head around the logic required, I imagine/hope this is something sql dev's come across regularly? Thanks!
OK, I worked it out, it's simple really. Hopefully this explanation helps someone else with the same issue in the future.
SELECT
myTable.TimestampUTC
, SUM(myTable.Actual_Value) as [Actual Value]
FROM
(
--My original query
) AS myTable
GROUP BY myTable.TimestampUTC

SELECT MAX Date T-SQL Subquery

I am attempting to SELECT rows from a table using a query like this
SELECT pminf_member, pminf_schmem
, pminf_date, pminf_fund
, pminf_cont, pminf_rate
, pminf_matrix
FROM pe_minvf
WHERE (pminf_member = 4380)
AND (pminf_schmem = 'M')
AND (pminf_date <= '03/30/2011')
AND (pminf_date =
(SELECT MAX(pminf_date) AS Expr1
FROM pe_minvf AS pe_minvf_1
WHERE (pminf_member = 4380)
)
)
AND (pminf_fund = 'LIFESTYLE')
What I should be getting from my subquery (I think) is a date of '01/01/2011' but when I run my query I am getting no results back.
If I replace the subquery with the hardcoded date I get the correct rows returned. For example
SELECT pminf_member, pminf_schmem
, pminf_date, pminf_fund
, pminf_cont, pminf_rate
, pminf_matrix
FROM pe_minvf
WHERE (pminf_member = 4380)
AND (pminf_schmem = 'M')
AND (pminf_date <= '03/30/2011')
AND (pminf_date = '01/01/2011')
AND (pminf_fund = 'LIFESTYLE')
This query returns the correct results.
Any ideas why the subquery is not returning the max date or if it is, why am I getting no rows back?
Thanks,
Tristan
You filter on different conditions in your queries.
It's pminf_fund = 'LIFESTYLE' in the subquery but pminf_schmem = 'M' in the outer query.
Also, you limit the date in the outer query and don't do it in the subquery.
If you just need the most recent record up to '03/30/2011', use this:
SELECT TOP 1
pminf_member, pminf_schmem, pminf_date, pminf_fund, pminf_cont, pminf_rate, pminf_matrix
FROM pe_minvf
WHERE pminf_member = 4380
AND pminf_schmem = 'M'
AND pminf_fund = 'LIFESTYLE'
AND pminf_date <= '03/30/2011'
ORDER BY
pminf_date DESC
SELECT pminf_member, pminf_schmem
, pminf_date, pminf_fund
, pminf_cont, pminf_rate
, pminf_matrix
FROM pe_minvf
WHERE (pminf_member = 4380)
AND (pminf_schmem = 'M')
AND (pminf_date =
(SELECT MAX(pminf_date) AS Expr1
FROM pe_minvf AS p
WHERE (p.pminf_member = 4380) AND
p.pminf_date <= '03/30/2011'
)
)
AND (pminf_fund = 'LIFESTYLE')
The query:
SELECT MAX(pminf_date) AS Expr
FROM pe_minvf AS pe_minvf_1
WHERE (pminf_member = 4380)
;
returns '01/01/2011' or something else?
Perhaps you want the same conditions on the subquery as in th emain query:
SELECT MAX(pminf_date) AS Expr
FROM pe_minvf AS pe_minvf_1
WHERE (pminf_member = 4380)
AND (pminf_schmem = 'M')
use a subquery to limit rows returned instead of the where clause. Use this as the subquery:
(SELECT MAX(pminf_date) AS Expr1
FROM pe_minvf AS pe_minvf_1
WHERE (pminf_member = 4380)
Keep the query basically the same...
Select same_fields_as you_did_before
from pe_minvf
inner join
(SELECT MAX(pminf_date) AS Maxdate, tablekey
FROM pe_minvf AS pe_minvf_1
WHERE pminf_member = 4380) a on a.tablekey = pe_minvf.table_key
where same_where_clause_you_had
Make sense? I wasn't sure what your table_key was on pe_minvf...you'll have to insert that yourself. I find using subqueires adn inner joining to them is a more effective way of limiting rows then having a subquery in your where clause
Twelfth!
Thanks for the proper syntax... I used it to resolve my similar problem de-jur (of-the-day)
Unless I am wrong, what I have below will work.. If it doesn't I will fix it here...
In the example below the data fields name have been cleansed but the syntax worked very fast.
By the way, there are 20,480 distinct device_id
declare
#BegDate varchar(20)=(select cast(CONVERT(VARCHAR(20), getdate()-2,101) as varchar(20)) + ' 10:59:59 PM')
,#EndDate varchar(20)=(select cast(CONVERT(VARCHAR(20), getdate()-0,101) as varchar(20)) + ' 11:00:00 PM')
select f1.ABC_ConfigProcStatusID,f1.DeviceID,f1.DBfilename ,f1.LastUpdatedDate
from dbo.ABC_ConfigProcStatus f1
inner join
(select distinct DeviceID,max(LastUpdatedDate) as max_DeviceIDdte
from dbo.ABC_ConfigProcStatus
where [Status]=2
and DeviceID not in(select ExclusionDeviceIDs from ABC_ConfigDeviceIDExclusionList)
group by DeviceID) f2
on f2.max_DeviceIDdte = f1.LastUpdatedDate
where [Status]=2
and f2.DeviceID = f1.DeviceID
and f1.DeviceID not in(select ExclusionDeviceIDs from ABC_ConfigDeviceIDExclusionList)
and LastUpdatedDate between #BegDate and #EndDate
and left(upper(f1.DeviceID),3) in ('XYZ','ZKO')
order by f1.LastUpdatedDate