Why are my results in SSRS different from SQL SMS? - sql-server

I've never seen this happen before, so I'm curious if anybody knows why, and maybe how I can correct for it.
This particular part of my code:
SELECT inv_num, co_line,
STUFF((
SELECT '/' + rs2.inv_pro_description
FROM #ReportSet rs2
WHERE rs2.inv_num = rs.inv_num AND
rs2.co_line = rs.co_line
FOR XML PATH('')), 1, 1, '') as ipd_combo
FROM #ReportSet rs
WHERE inv_pro_seq IS NOT NULL AND inv_pro_description <> 'Less Previously Invoiced'
GROUP BY inv_num, co_line
results in a correct concatenation of my two results, e.g., "10% Advance/Fixed $5 Required" in this case. However, when utilizing this procedure in SSRS, my field contains instead "Fixed $5 Required/10% Advance".
I have grown accustomed to being able to predict my SSRS reports based on running SQL queries, so this confused me.
I don't really understand the STUFF / XML PATH code, of course. I've copied it from somebody else (on this website, naturally) so I know that might have something to do with it.

To get consistent ordering, add an order by clause to your inner select:
SELECT inv_num, co_line,
STUFF((
SELECT '/' + rs2.inv_pro_description
FROM #ReportSet rs2
WHERE rs2.inv_num = rs.inv_num AND
rs2.co_line = rs.co_line
ORDER BY rs2.inv_pro_seq --********
FOR XML PATH('')), 1, 1, '') as ipd_combo
FROM #ReportSet rs
WHERE inv_pro_seq IS NOT NULL AND inv_pro_description <> 'Less Previously Invoiced'
GROUP BY inv_num, co_line
The commented asterisks indicate the added line.
(I answered in comments, but adding this here for consistency/permanency).

Related

SQL Server 2008: Null Return in Dynamic XML Query

I have a set of dynamic queries which return XML as varchars, see below.
Example query:
set #sqlstr = 'Select ''<?xml version="1.0" encoding="windows-1252" ?>'' + ''<File_Name><Location>'' + (Select a,b,c from table for xml path(''Row'')) + </Location></File_name>'''
exec(#sqlstr)
This works a treat until the select a,b,c ... query is NULL. Then I don't receive the outside elements as you'd expect like:
<?xml version="1.0" encoding="windows-1252"><File_Name><Location><Row></Row></Location></File_name>
All I receive is NULL
After a bit of Googling I find the issue is the concatenation of NULL results is a complete NULL Result. However I cannot find one solution gives me what I'd expect to be the result.
I've tried (not to say I have tried correctly)
IsNull(Exec(#sqlstring),'*blank elements*')
xsnil (doesn't seem to work in dynamic queries)
#result = exec(#sqlstring) then isnull and select
Anyone have a better solution? (preferably small due to multiple such queries)
I think you need something like this:
set #sqlstr = 'Select ''<?xml version="1.0" encoding="windows-1252" ?><File_Name><Location>'' + (Select IsNull(a, '') as a, IsNull(b, '') as b,IsNull(c, '') as c from table for xml path(''Row'')) + </Location></File_name>'''
exec(#sqlstr)

Concat the values in a string with SQL Server

I want to select a list of items and part numbers for for each item as a string:
SELECT top 100 *
FROM ii
OUTER APPLY
(SELECT def, ( ipr.part_number + ',') as prt
FROM ipr
WHERE ii.item_id = ipr.item_id
FOR XML PATH('') ) PN
The error is:
[Error Code: 8155, SQL State: S0002] No column name was specified for
column 1 of 'PN'.
How can I fix this?
I think that your whole OUTER APPLY statement generates one XML for both default_part_number and concatenated string, which(the whole XML) doesn't have a name.
What you could try to do would be adding alias like this AS PN(TestThis).
However, I don't think that you're expecting result you're going to get. It would better if you'd give us some example data and expected output. It will be easier for us to solve your problem in that case.
The combination of XML and STUFF is funny but perfectly fitting to your needs.
First you concat your strings with the ', ' in front, then you must return your XML with ", TPYE). You must read the result with ".value()" and use STUFF to replace the first ', '.
You'll find a lot of exampels in the net...

SQL limit for XML type

I am actually working on a large database and I am querying the following data;
My Query:
SELECT ldd.LDistCD, ldd.LDistDescPay
FROM LDetail ldd
INNER JOIN LDist ld
ON ldd.ID = ld.ID
AND ld.ID = '019458'
AND ld.LDistType = 'F'
Result:
What I am doing next, is to loop across the results (27873) in my VB codes to concatenate the data in the following format;
LDistCD + '|' + LDistDescPay
Normally that would be a very time consuming time looping through all these rows. Hence to optimise the work, I am using the following query which should already concatenate the data for me;
SELECT stuff((SELECT ',' + ldd.LddLabourDistCD + '|' + ldd.LddLabourDistDescPay
FROM LDetail ldd
INNER JOIN LDist ld
ON ldd.ID = ld.ID
AND ld.ID = 019425 AND ld.LDistType = 'F'
FOR XML
PATH ('')), 1, 1, '')
Everything is working fine except for the result, whereby some data is being truncated!! Running the last query on MS SQL Server returns the concatenate result but it is not complete. I get the impression there's a limit to the result which is being exceeded.
Can anyone help on the issue please?
Difficult for me to upload the db or the result but just to tell you that the 27873 rows, when concatenated in one string, is not fitting in the result.
The truncation you are seeing is specific to SQL Server Management Studio (SSMS). If you go to the Query menu and select Query Options..., then go to Results and then to Grid, you should see on the right side a section for "Maximum Characters Retrieved". The "Non XML data" has a max of 65,535 (which should also be the default) and the "XML data" is a drop-down with options:
1 MB
2 MB (default)
5 MB
Unlimited
Since the XML datatype can bring back more than 65,535 characters, you can convert your output to XML (this is only needed when using SSMS; client libraries should pull back the full string):
SELECT CONVERT(XML,
stuff((SELECT ',' + ldd.LddLabourDistCD + '|' + ldd.LddLabourDistDescPay
FROM LDetail ldd
INNER JOIN LDist ld
ON ldd.ID = ld.ID
AND ld.ID = 019425
AND ld.LDistType = 'F'
FOR XML PATH ('')), 1, 1, '')
)

SQL Server : Like Syntax and Add operator Error

I am using this syntax and it should work well if only it doesn't get an error.
SELECT
e.user_key,
e.char_key,
CONVERT(VARCHAR,substring(e.char_data, 9, 16)) AS name,
p.CHAR_DATA
FROM
CHAR_DATA0 AS e
INNER JOIN
CHAR_DATA1 AS p ON e.CHAR_KEY = p.CHAR_KEY
WHERE
p.CHAR_DATA LIKE '%'+CAST(cast(reverse(CONVERT(BINARY, 9998)) as BINARY(2)) AS BINARY(2))+'%'
ORDER BY
char_key
I need help. How to change this code for it to work?
CHAR_DATA column is of type BINARY(2000)
I have data like so: (got it using select)
0x04005C03020F2789080100000F278908010000FFFFFFFFFFFFFF0E2787080100000E278708010000FFFFFFFFFFFFFFBA3B8C08000000BB3B8C080000000F2789080100000F278908010000FFFFFFFFFFFFFF0E2787080100000E278708010000FFFFFFFFFFFFFFBC3B8C08000000BD3B8C080000000F2789080100000F278908010000FFFFFFFFFFFFFF0E2787080100000E278708010000FFFFFFFFFFFFFFBE3B8C08000000BF3B8C080000000F2789080100000F278908010000FFFFFFFFFFFFFF0E2787080100000E278708010000FFFFFFFFFFFFFFC03B8C08000000C13B8C08000000B5388B08020000B5388B08020000FFFFFFFFFFFFFF0E2787080100000E278708010000FFFFFFFFFFFFFFBA3B8C08000000BB3B8C08000000B5388B08020000B5388B08020000FFFFFFFFFFFFFF0E2787080100000E278708010000FFFFFFFFFFFFFFBC3B8C08000000BD3B8C080000000E2789080100000E278908010000FFFFFFFFFFFFFF0E2787080100000E278708010000FFFFFFFFFFFFFFBE3B8C08000000BF3B8C080000000E2789080100000E278908010000FFFFFFFFFFFFFF0E2787080100000E278708010000FFFFFFFFFFFFFFC03B8C08000000C13BFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF0F27FFFF0100000F27FFFF0100000E2789080000000E278908000000FFFFFFFFFFFFFF7E107F08000000EC168408000000B0177D080000000F27FFFF0100000F27FFFF0100000E2789080000000E27890800000052167C081E000052167C081E0000E2167D08000000271F2005000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF0E2787080100000E27870801000052167C081E000052167C081E0000FFFFFFFFFFFFFF13127F08000000C813FFFF1E0000C813FFFF1E00000E2787080100000E27870801000028127A08000000BF3B2D05000000FFFFFFFFFFFFFF13127F08000000C813FFFF1E0000C813FFFF1E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF28127A08000000FFFFFFFFFFFFFF1B1A80081A00001B1A80081A0000E915FFFF1B0000E915FFFF1B000023067A0800000024147B0800000020120D05000000084792080100001B1A80081A00001B1A80081A0000E915FFFF1B0000E915FFFF1B000025067A0800000024147B0800000020120D05000000E21610050000000000009D000000FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
I need to search somewhere in those lines if it contains the entry I'm trying to find.
What I'm trying to find is always 2 bytes. So I'm looking for 0x0E27 in the syntax above.
This is a working syntax but its not what I want to do:
SELECT
CONVERT(INT,cast(reverse(substring(char_data, 37, 2)) as BINARY(2))) AS helm
FROM CHAR_DATA0
WHERE CHAR_KEY = 5
Another this is if I use nvarchar(MAX) it gives results that doesn't even contain the data I'm trying to find.
where Convert(varChar(4000), CHAR_DATA,2 ) like '%' + Convert(varChar(4), CONVERT(BINARY(2), 9998),2 )+'%'
I tried just selecting that like clause, mainly because I don't need your schema (tables) to do so, and found a bug (I think) already:
SELECT '%' + CAST( CAST(REVERSE(CONVERT(BINARY, 9998)) as BINARY(2)) AS BINARY(2) ) + '%'
produces:
Msg 402, Level 16, State 1, Line 1
The data types varchar and binary are incompatible in the add operator.
... where as (changing the overal result type to varchar):
SELECT '%' + CAST( CAST(REVERSE(CONVERT(BINARY, 9998)) as BINARY(2)) AS VARCHAR(2) ) + '%'
produces (we'll need some luck with the encoding here):
%'% -- that is: percent, apostrophe, beam (the musical note), percent
Maybe that's the whole problem (though I doubt it)? Try it and let-is know how you go. I doubt it because I guess that if it was the whole problem then you would have worked it out for yourself from the error message (that I presume you would have gotten from SQL-Server).
Cheers. Keith.

Intra-SELECT variables?

Would it be possible to alias an expression returned by a SELECT statement in order to refer to it in other parts of this same SELECT as if it would be a column among others ?
A kind of "temporary variable" whose scope would be limited to the SELECT statement, a little bit like the WITH clause before a SELECT to use a temporary named recorset.
A naive sample of what I'd like to achieve :
SELECT
FIRSTNAME + ' ' + NAME AS FULLNAME,
CASE WHEN LEN(FULLNAME)>3 THEN 1 ELSE 0 END AS ISCORRECT
FROM USERS
where FULLNAME could be used to determine the subsequent output field ISCORRECT, though not being a real column of the table USERS... instead of this laboured error-prone (but working) copy/paste :
SELECT
FIRSTNAME + ' ' + NAME AS FULLNAME,
CASE WHEN LEN(FIRSTNAME + ' ' + NAME)>3 THEN 1 ELSE 0 END AS ISCORRECT
FROM USERS
This sample well describes what I want, but I can easily imagine similar needs where FULLNAME might also be used in other parts of the SELECT statement : in a JOIN, in the WHERE, in a GROUP BY, ORDER BY, etc.
PS : I use SQL Server 2005 but would be also interested in any 2008-specific answer.
Thanks a lot ! :-)
Edit :
In spite of my high respect towards those of you proposing to use a side- or inner-query, I don't feel at ease with such possibilities. My sample really is a naive one. The true queries are rather with 30 output fields including complex expressions (including calls to CLR functions), 15 inner/left outer joins, and 20 additionnal where criteria. I suspect I had rather not multiplying to many indirections towards co-queries if I can avoid it.
I believe you would have to put it in an inner query, and then be able to refer to it outside of the query.
Simplest example based on yours:
select a.fullname, case when len(a.fullname) > 3 then 1
else 0 end as incorrect
from (select firstname + ' ' + name as fullname
from users) a
Example with a CTE
;with names (FULLNAME) as (
SELECT FIRSTNAME + ' ' + NAME
FROM USERS
) select
FULLNAME,
CASE WHEN LEN(FULLNAME) > 3 THEN 1 ELSE 0 END AS ISCORRECT
FROM names
You can use cross apply to concatenate strings or do calculations etc.. that involves just the current row.
select T.fullname,
case when len(T.fullname) > 3
then 1
else 0
end iscorrect
from users as U
cross apply
(select U.firstname+' '+U.name) as T(fullname)
order by T.fullname
Though not very satisfied with it, I choose (temporarily ?) a third option : I avoid co-queries and copy/pasting my complex hard-to-read expression (here symbolized by the simple one aliased as FULLNAME) by embeddind it in a scalar function... which is therefore called several times in different parts of my SELECT.
SELECT
dbo.GetFULLNAME(FIRSTNAME,NAME) AS FULLNAME,
CASE WHEN LEN(dbo.GetFULLNAME(FIRSTNAME,NAME))>3 THEN 1 ELSE 0 END AS ISCORRECT
FROM USERS
What do you think of it ?
(I precise that though more complex and unreadable than in my OP, the real expression remains a "simple" matter of string manipulation using several input fields, and doesn't involve any sub-querying or anything like that).

Resources