MSSQL 2012 - Why is AVG & TRY_CONVERT not returning the correct value? - sql

I am using MSSQL 2012 and I am trying to use AVG together with TRY_CONVERT on a table column with the following datatype: nvarchar(255), NOT NULL
First before I try to query using AVG & TRY_CONVERT, this is the data that I want to get the AVG value out of using this query:
And this is the results after using AVG and TRY_CONVERT, 0 rows returned.
I also tried to use a subquery then i got 18 row returned, but with value NULL, i skipped out on AVG just to see if i was getting the correct values.. but it seems not, i also included the p.serialnumber column to show that its the correct rows that was returned, its just the value NULL that somehow appears after TRY_CONVERT.
UPDATE!:
When I execute the query below which target data that has a "." separator (qtv2.qtv_qteid = 58 (instead of 63)) , it works! So the issue is the "," separator. Anyone know solution to this??
declare #ProjectSelection nvarchar(10)
set #ProjectSelection = 'C82007588'
SELECT AVG(TRY_CONVERT(numeric(10,5), avgcap))
FROM
(
select qtv2.qtv_result as avgcap
from ProductionOrder PO
left join CustomerOrder co on co.CustomerOrderId=po.customerorderid
left join ProductionOrderProperty pop on pop.ProductionOrderId=po.productionorderid
left join product p on p.ProductionOrderId=po.productionorderid
left join QualityTestValues qtv on qtv.qtv_productid=p.ProductId
left join QualityTestValues qtv2 on qtv2.qtv_productId=p.ProductId
where pop.Value=#ProjectSelection and pop.name = 'project' and po.ProductTypeId = 1
and qtv2.qtv_qteid = 58 and qtv2.qtv_valid = 1 and qtv.qtv_ProductSegmentId = 144 and qtv.qtv_valid = 1
and qtv.qtv_qteid = 51 and qtv.qtv_result = 'J'
group by co.CustomerName, pop.Value, qtv2.qtv_result, p.SerialNumber
) A
Result:
(No column name)
22.200000

How about your compatibility level? A similar question can be found here:
TRY_CONVERT fails on SQL Server 2012
Although your server version is 2012, a lower compatibility level can cause the try_convert to be unavailable for use in your database. You can check this by running the following code in your specific database and afterwards on for instance the master database.
DECLARE #b VARCHAR(10) = '12312'
SELECT TRY_CONVERT(INT,#b)

You can take your first query and do something like this:
SELECT AVG(TRY_CONVERT(numeric(10,5), avgcap))
FROM
(
-- Insert your first query here.
) A
This should give you the average of the numbers.
EDIT
Here is a workable example that should return 24.000000.
SELECT AVG(TRY_CONVERT(numeric(10,5), A))
FROM
(
SELECT '22.5' AS A
UNION
SELECT '23.5' AS A
UNION
SELECT '26.0' AS A
) B

I found out the solution, using TRY_PARSE instead of TRY_CONVERT.
DECLARE #ProjectSelection nvarchar(10)
SET #ProjectSelection = 'C82007588'
SELECT AVG(avgcap) as avgcap
FROM
(
SELECT qtv2.qtv_result, TRY_PARSE( qtv2.qtv_result AS NUMERIC(10,3)) avgcap
FROM ProductionOrder PO
LEFT JOIN CustomerOrder co on co.CustomerOrderId=po.customerorderid
LEFT JOIN ProductionOrderProperty pop on pop.ProductionOrderId=po.productionorderid
LEFT JOIN product p on p.ProductionOrderId=po.productionorderid
LEFT JOIN QualityTestValues qtv on qtv.qtv_productid=p.ProductId
LEFT JOIN QualityTestValues qtv2 on qtv2.qtv_productId=p.ProductId
WHERE pop.Value=#ProjectSelection
AND pop.name = 'project'
AND po.ProductTypeId = 1
AND qtv2.qtv_qteid = 63
AND qtv2.qtv_valid = 1
AND qtv.qtv_ProductSegmentId = 144
AND qtv.qtv_valid = 1
AND qtv.qtv_qteid = 51
AND qtv.qtv_result = 'J'
GROUP BY co.CustomerName, pop.Value, qtv2.qtv_result, p.SerialNumber
) A`
Results:
avgcap
21264.850000

Related

Single Query To Select Based On Parameters If Or not supplied

I have used SqlDataSource and have a select query based on District & Zone as below
SELECT a.[committee_id] memberid, a.[membername], a.[memberemail], a.[memberdesignation], a.[membercreatedby],b.districtname AS district,b.districtid,c.zone_name AS zone,c.zoneid
FROM [committee_details] a
LEFT JOIN district_master b on b.districtid=a.districtid
LEFT JOIN zone_master c on c.districtid=a.districtid and c.zoneid = a.zoneid
WHERE (a.[membercreatedby] = 'director') AND ((convert(varchar,a.districtid) LIKE '%2%') AND (convert(varchar,a.zoneid) LIKE '%25%')) ORDER BY a.[committee_id] DESC
It's an inline query. I have tried above query but not able to figure out how to Select condition based.
I want if district supplied then Select according to District, if both District & Zone supplied then Select according to both & If nothing supplied then Select All. But should be in single query. How should I do this?
First, fix your query so you are not using meaningless table aliases. Use table abbreviations! I would also drop all the square braces; they just make the query harder to write and to read.
Basically, you want comparisons with NULL in the WHERE clause. I have no idea why your sample code uses LIKE, particularly columns that appear to be numbers. Nothing in the question explains why LIKE is used for the comparison, so the idea is:
SELECT cd.committee_id as memberid, cd.membername,
cd.memberemail, cd.memberdesignation, cd.membercreatedby,
dm.districtname AS district, dm.districtid,
zm.zone_name AS zone, zm.zoneid
FROM committee_details cd LEFT JOIN
district_master dm
ON cd.districtid = dm.districtid LEFT JOIN
zone_master zm
ON zm.districtid = cd.districtid AND
zm.zoneid = cd.zoneid
WHERE cd.membercreatedby = 'director') AND
(cd.districtid = #district or #district is null) AND
(cd.zoneid = #zone or #zone is null)
ORDER BY cd.[committee_id] DESC;
If you were using LIKE, then I would phrase the logic like:
WHERE cd.membercreatedby = 'director') AND
(cast(cd.districtid as varchar(255)) like #district) AND
(cast(cd.zoneid as varchar(255)) like #zone)
And pass in the patterns as '%' when you want all values to match. This assumes that the columns in cd are not NULL. If they can be NULL, then you want an explicit comparison, as in the first example.
If I got the question right then you can use parameters and compare to the column itself if the values are not supplied or not present.
try the following:
SELECT a.[committee_id] memberid, a.[membername], a.[memberemail], a.[memberdesignation], a.[membercreatedby],b.districtname AS district,b.districtid,c.zone_name AS zone,c.zoneid
FROM [committee_details] a
LEFT JOIN district_master b on b.districtid=a.districtid
LEFT JOIN zone_master c on c.districtid=a.districtid and c.zoneid = a.zoneid
WHERE (a.[membercreatedby] = 'director')
AND b.districtname = isnull(nullif(#districtname, ''), b.districtname)
AND c.zone_name = isnull(nullif(#zone_name, ''), c.zone_name)
ORDER BY a.[committee_id] DESC

Dice query only returning with a specific fields condition

We're doing a dice olap query that gets a certain production company's total revenue of a specific year on the schema below:
Using this query:
SELECT PC.name, RC.year, SUM(revenue) as total_revenue
FROM movies_reception_facts MR
JOIN ref_calendar RC ON MR.release_date_key = RC.date_key
JOIN pc_groups PG ON MR.pc_group_key = PG.pc_group_key
JOIN movies_pc MP ON PG.pc_group_key = MP.pc_group_key
JOIN production_companies PC ON MP.pc_id = PC.pc_id
WHERE PC.pc_id IN(
SELECT pc_id
FROM production_companies
WHERE name = 'Disney') AND
RC.date_key IN(
SELECT RC.date_key
FROM ref_calendar
WHERE RC.year = 2014
)
GROUP BY (PC.name, RC.year)
The problem is that, it's only returning results when the year is set to 2014: WHERE RC.year = 2014. Any other value would return an empty row.
I'm not sure if this fixes your problem, but that subquery is problematic. First, if you did use a subquery, it would be:
RC.date_key IN(
SELECT RC2.date_key
FROM ref_calendar RC2
WHERE RC2.year = 2014
)
But a subquery is not necessary. You can just replace the logic with:
RC.year = 2014
Then putting this condition in the IN clause is silly. It should be a filter in the outer where. And since the tables are already joined in, I think you just want:
WHERE pc.name = 'Disney' AND
RC.year = 2014
That said, I'm not sure if this fixes your problem of no data being returned for other years.

Select varchar max in Codeigniter returns unknown characters

In sql management studio, it returns the text. But in codeigniter it returns something like:
n?g%'!?>?eHH!!X??HI!??
??W.
But if I changed it to varchar(8000) it returns the text.
Why?
Here's my query:
SELECT TOP(50) A.*,
RIGHT('000'+ISNULL(CONVERT(VARCHAR,A.MajorArticleCode), ''),3) AS MajorArticleCode, B.MajorArticleDesc,
RIGHT('000'+ISNULL(CONVERT(VARCHAR,A.MinorArticleCode), ''),2) AS MinorArticleCode, C.MinorArticleDesc
FROM LIB_Items A
LEFT JOIN LIB_Major_Articles B ON A.ACCode = B.ACCode AND A.MajorArticleCode = B.MajorArticleCode
LEFT JOIN LIB_Minor_Articles C ON A.ACCode = C.ACCode AND A.MajorArticleCode = C.MajorArticleCode AND A.MinorArticleCode = C.MinorArticleCode
And here's my LIB_Items table structure
LIB_Items table structure

Oracle 9i SQL query - join multiple time the same table

I've a strange behavior with a simple SQL query. I work on Oracle 9i.
I just wanna be sure there is no stupid error in my query. If anyone can tell me what I'm doing wrong. Here's the query :
select p.PARTNUM,
p.N_DATAA, dataa1.ID_DATA as ID_DATAA,
p.N_DATAF, dataf1.ID_DATA as ID_DATAF,
p.N_DATAS, datas1.ID_DATA as ID_DATAS
from PIECES p
left join DATA dataa1 on
dataa1.N_DATA = p.N_DATAA AND
dataa1.REV_DATA = ( select max(dataa2.REV_DATA) from DATA dataa2
where dataa2.N_DATA = p.N_DATAA )
left join DATA dataf1 on
dataf1.N_DATA = p.N_DATAF AND
dataf1.REV_DATA = ( select max(dataf2.REV_DATA) from DATA dataf2
where dataf2.N_DATA = p.N_DATAF )
left join DATA datas1 on
datas1.N_DATA = p.N_DATAS AND
datas1.REV_DATA = ( select max(datas2.REV_DATA) from DATA datas2
where datas2.N_DATA = p.N_DATAS )
where p.PARTNUM='MYPARTNUM';
and here is the result :
"PARTNUM" "N_DATAA" "ID_DATAA" "N_DATAF" "ID_DATAF" "N_DATAS" "ID_DATAS"
"MYPARTNUM" "A23240" "300" "F4130" "398" "S2330" ""
My problem appears on the field ID_DATAS (an ID_DATAS should be returned, I'm sure, see below), it acts as if it ignores the last join and retrieve no data. If I delete the SECOND join, it works perfectly. It seems like if Oracle does not support more than 2 left join... (???)
Here an other example when I switch the two last left join (in this case the problem appears on ID_DATAF) :
select p.PARTNUM,
p.N_DATAA, dataa1.ID_DATA as ID_DATAA,
p.N_DATAF, dataf1.ID_DATA as ID_DATAF,
p.N_DATAS, datas1.ID_DATA as ID_DATAS
from PIECES p
left join DATA dataa1 on
dataa1.N_DATA = p.N_DATAA AND
dataa1.REV_DATA = ( select max(dataa2.REV_DATA) from DATA dataa2
where dataa2.N_DATA = p.N_DATAA )
left join DATA datas1 on
datas1.N_DATA = p.N_DATAS AND
datas1.REV_DATA = ( select max(datas2.REV_DATA) from DATA datas2
where datas2.N_DATA = p.N_DATAS )
left join DATA dataf1 on
dataf1.N_DATA = p.N_DATAF AND
dataf1.REV_DATA = ( select max(dataf2.REV_DATA) from DATA dataf2
where dataf2.N_DATA = p.N_DATAF )
where p.PARTNUM='MYPARTNUM';
and here is the result :
"PARTNUM" "N_DATAA" "ID_DATAA" "N_DATAF" "ID_DATAF" "N_DATAS" "ID_DATAS"
"MYPARTNUM" "A23240" "300" "F4130" "" "S2330" "400"
Thank you for your help :)
EDIT : add fully qualified column names in queries (does not solve my problem)
You are probably experiencing a bug with your old version of Oracle. Oracle 9i was the first version to support ANSI join and came with a few bugs with ANSI-join syntax.
Your query won't run in an up-to-date (11.2) Oracle db (SQLFiddle), you will run into:
ORA-01799: a column may not be outer-joined to a subquery
So the bug in your Oracle version is that this query shouldn't return any result. In any case make sure that you're running the latest patch set. Also it may be a good idea to plan an upgrade, this version is deprecated -- extended support ended 3 years ago!
You'll have to rewrite your query, for instance like this:
SQL> WITH filtered_data AS (
2 SELECT n_data, rev_data, id_data
3 FROM DATA d
4 WHERE rev_data = (SELECT MAX(rev_data)
5 FROM DATA d_in
6 WHERE d_in.n_data = d.n_data)
7 )
8 SELECT p.partnum,
9 p.n_dataa,
10 A.id_data AS id_dataa,
11 p.n_dataf,
12 F.id_data AS id_dataf,
13 p.n_datas,
14 S.id_data AS id_datas
15 FROM pieces p
16 LEFT JOIN filtered_data A ON A.n_data = p.n_dataa
17 LEFT JOIN filtered_data S ON S.n_data = p.n_datas
18 LEFT JOIN filtered_data F ON F.n_data = p.n_dataf
19 WHERE p.PARTNUM = 'MYPARTNUM';
PARTNUM N_DATAA ID_DATAA N_DATAF ID_DATAF N_DATAS ID_DATAS
------------- -------- --------- -------- --------- -------- ---------
MYPARTNUM A23240 300 F4130 398 S2330 400

issue with MAX statement in t-sql code

This is the code:
Select BCPP.*
from ViewPBCPP BCPP
inner join
(
Select MBC.PC PC
,MRT.Name CT
,Max(dbo.CalcDatefromUTC(MBC.CreatedDate)) as LRDate
from TableBACC MBC
inner join TableSC.RT MRT
ON MBC.RTid = MRT.id
where MBC.Isdeleted = 'False'
and MBC.PC <> 'NULL'
Group by MBC.PC
,MRT.Name
) MBCR
ON BCPP.P_id = MBCR.PC
and BCPP.CreatedDate = MBCR.LRDate
and BCPP.CT = MBCR.CT
Now Max(dbo.CalcDatefromUTC(MBC.CreatedDate)) is actually a function
Query above works fine with Max(dbo.CalcDatefromUTC(MBC.CreatedDate))
Now when I write
Max(dbo.CalcDatefromUTC(MBC.CreatedDate)) + Min(dbo.CalcDatefromUTC(MBC.CreatedDate))
I cannot extract any values at all from this query written above
If I write just
(dbo.CalcDatefromUTC(MBC.CreatedDate))
it gives me error that it does not contained aggregate function or the group by function
I actually want this
(dbo.CalcDatefromUTC(MBC.CreatedDate))
so that I can use all the values of this function rather than just MAX values of it
How can I change this code written above to achieve my objective??
Anyone??
You can't have dbo.CalcDatefromUTC(MBC.CreatedDate) in the SELECT list as neither you can have MBC.CreatedDate because it's not in the GROUP BY list.
You can have MAX(MBC.CreatedDate) though because it uses an aggregate function (MAX) on thta column. You can also have:
dbo.CalcDatefromUTC(MAX(MBC.CreatedDate)) as LRDate
which is the same actually (although maybe a bit faster), as:
MAX(dbo.CalcDatefromUTC(MBC.CreatedDate)) as LRDate
From your comments, I assume the above is not very helpful. Perhaps grouping by MBC.CreatedDate as well is what you want:
Select BCPP.*
from ViewPBCPP BCPP
inner join
(
Select MBC.PC PC
,MRT.Name CT
,dbo.CalcDatefromUTC(MBC.CreatedDate) as LRDate
from TableBACC MBC
inner join TableSC.RT MRT
ON MBC.RTid = MRT.id
where MBC.Isdeleted = 'False'
and MBC.PC <> 'NULL'
Group by MBC.PC
,MBC.CreatedDate --- added
,MRT.Name
) MBCR
ON BCPP.P_id = MBCR.PC
and BCPP.CreatedDate = MBCR.LRDate
and BCPP.CT = MBCR.CT