Sql sorting wrong - sql-server

Why does my sorting not work as it should? If i click to sort the value of my select under then it only sorts after the first number so if i have values like 100,33,2100,4432 then i get this order 100,2100,33,4432
How can 100 be smaller then 33 and so on...
SELECT Replace(
CONVERT(VARCHAR,
CONVERT(INTEGER, Sum(
Isnull(
a.planabsatz_mt1 + a.planabsatz_mt2
+ a.planabsatz_mt3 + a.planabsatz_mt4
+ a.planabsatz_mt5 + a.planabsatz_mt6
+ a.planabsatz_mt7 + a.planabsatz_mt8
+ a.planabsatz_mt9 + a.planabsatz_mt10
+ a.planabsatz_mt11 + a.planabsatz_mt12, 0))), 1),
'.00', '')

You've converted your values to strings in the select statement you posted.
So, doing an alpha sort, 100 does come before 33.

You're converting the number to a varchar before sorting. Try this:
SELECT Replace(
CONVERT(INTEGER, Sum(
Isnull(
a.planabsatz_mt1 + a.planabsatz_mt2
+ a.planabsatz_mt3 + a.planabsatz_mt4
+ a.planabsatz_mt5 + a.planabsatz_mt6
+ a.planabsatz_mt7 + a.planabsatz_mt8
+ a.planabsatz_mt9 + a.planabsatz_mt10
+ a.planabsatz_mt11 + a.planabsatz_mt12, 0))),
'.00', '')

Related

SQL Server 2008 - WHILE Loop

I have a problem that I can not solve, my final goal is to make a trigger that runs every time it is inserted in the 'factura' table and then fill an intermediate table that only has one field (varchar max), because ?, because I have a component in Java that reads this field and generates a file.txt that he later used, but I have a problem that I can not solve, I was seeing what could be with a cursor or better still with a while loop but I am entangled, the BD manager that I use is SQL Server 2008, the select query that I use to generate the data that will be filled in the intermediate table in the trigger, consists of two parts, the header and the details, which I seek to do is that it only shows one row per header, but since there are more than 1 detail in some cases it shows repeated rows.
This is my query:
select
--HEADER(CB),
'CB' + '|' + CONVERT(varchar(10),(CONVERT(DATE, f.FECHA))) + '|' +
'20601140897' + '|' + '03' + '|' +
SUBSTRING(f.SERIE, 1, 2) + '0' + SUBSTRING(f.SERIE, 3, 2) + '-' +
REPLACE(STR(f.NUMERO, 8), SPACE(1), '0') + '|' +
CASE
WHEN f.CODIGO = '' THEN '99999999'
ELSE f.CODIGO
END + '|' + '0' + '|' +
CASE
WHEN f.NOMBRE ='' THEN 'Clientes varios'
ELSE f.NOMBRE
END + '|PEN|' +
CONVERT(varchar(13), (CAST(f.SUBTOTAL AS decimal(10, 2)))) +
'|0.00|0.00|' +
CONVERT(varchar(13), (CAST(f.IMPUESTO AS decimal(10, 2)))) +
'|0.00|0.00|0.00|0.00|' +
CONVERT(varchar(13), (cast(f.TOTAL as decimal(10, 2)))) + '|0.00|0.00|' +
'MONTO TOTAL' + '|||||||1000||||0.00|0.00|0.00||' + CHAR(13) + CHAR(10) +
--DETAIL(DF)
'DB' + '|' + 'NUMBER OF ROW' + '|' + d.PRODUCTO + '|' + 'NIU' + '|' + '1' + '|' +
d.DESCRIPCIO + '|' + CONVERT(varchar(13),(ROUND((d.PRECIO/1.18), 2))) + '|' +
CONVERT(varchar(13), (cast(d.PRECIO as decimal(10, 2)))) + '|' +
CONVERT(varchar(13), (ROUND(((d.PRECIO/1.18) * 0.18), 2))) + '|10|0.00||' +
CONVERT(varchar(13), (cast(d.TOTAL as decimal(10, 2)))) + '|0.00||0.00||'
FROM
factura f
FULL JOIN
detalle d ON f.NUMERO = d.NUMERO
FULL JOIN
clientes c ON f.CODIGO = c.codigo
And this is what it shows:
CB|2017-10-08|20601140897|03|B001-00002224|000700323|0|Clientes
varios|PEN|25.42|0.00|0.00|4.58|0.00|0.00|0.00|0.00|30.00|0.00|0.00|MONTO
TOTAL|||||||1000||||0.00|0.00|0.00|| DB|NUMBER OF
ROW|220|NIU|1|TODO EL
DIA|8.47|10.00|1.53|10|0.00||10.00|0.00||0.00||
CB|2017-10-08|20601140897|03|B001-00002224|000700323|0|Clientes
varios|PEN|25.42|0.00|0.00|4.58|0.00|0.00|0.00|0.00|30.00|0.00|0.00|MONTO
TOTAL|||||||1000||||0.00|0.00|0.00|| DB|NUMBER OF
ROW|230|NIU|1|10 MIN FIN DE
SEMANA|16.94|20.00|3.06|10|0.00||20.00|0.00||0.00||
What I look for:
CB|2017-10-08|20601140897|03|B001-00002224|000700323|0|Clientes
varios|PEN|25.42|0.00|0.00|4.58|0.00|0.00|0.00|0.00|30.00|0.00|0.00|MONTO
TOTAL|||||||1000||||0.00|0.00|0.00|| DB|NUMBER OF
ROW|220|NIU|1|TODO EL
DIA|8.47|10.00|1.53|10|0.00||10.00|0.00||0.00|| DB|NUMBER OF
ROW|230|NIU|1|10 MIN FIN DE
SEMANA|16.94|0.00|3.06|10|0.00||20.00|0.00||0.00||
Somebody could help me? or give me a structure to be able to achieve it, please, I'd be really grateful.
Here is the query, which will append the detail data when there is an identical header data. Query is slow as it involves JOIN on string and large column, You can replace CTE with temp table and by adding index may give a better performance.
;WITH CTE AS (
select
--HEADER(CB),
'CB' + '|' + CONVERT(varchar(10),(CONVERT(DATE, f.FECHA))) + '|' +
'20601140897' + '|' + '03' + '|' +
SUBSTRING(f.SERIE, 1, 2) + '0' + SUBSTRING(f.SERIE, 3, 2) + '-' +
REPLACE(STR(f.NUMERO, 8), SPACE(1), '0') + '|' +
CASE
WHEN f.CODIGO = '' THEN '99999999'
ELSE f.CODIGO
END + '|' + '0' + '|' +
CASE
WHEN f.NOMBRE ='' THEN 'Clientes varios'
ELSE f.NOMBRE
END + '|PEN|' +
CONVERT(varchar(13), (CAST(f.SUBTOTAL AS decimal(10, 2)))) +
'|0.00|0.00|' +
CONVERT(varchar(13), (CAST(f.IMPUESTO AS decimal(10, 2)))) +
'|0.00|0.00|0.00|0.00|' +
CONVERT(varchar(13), (cast(f.TOTAL as decimal(10, 2)))) + '|0.00|0.00|' +
'MONTO TOTAL' + '|||||||1000||||0.00|0.00|0.00||' + CHAR(13) + CHAR(10) HeaderData,
--DETAIL(DF)
'DB' + '|' + 'NUMBER OF ROW' + '|' + d.PRODUCTO + '|' + 'NIU' + '|' + '1' + '|' +
d.DESCRIPCIO + '|' + CONVERT(varchar(13),(ROUND((d.PRECIO/1.18), 2))) + '|' +
CONVERT(varchar(13), (cast(d.PRECIO as decimal(10, 2)))) + '|' +
CONVERT(varchar(13), (ROUND(((d.PRECIO/1.18) * 0.18), 2))) + '|10|0.00||' +
CONVERT(varchar(13), (cast(d.TOTAL as decimal(10, 2)))) + '|0.00||0.00||' DetailData
FROM factura f FULL JOIN detalle d ON f.NUMERO = d.NUMERO
FULL JOIN clientes c ON f.CODIGO = c.codigo
)
select HeaderData+STUFF((SELECT '|'+ DetailData
FROM CTE C
WHERE C.HeaderData=T.HeaderData
FOR XML PATH('')),1,1,'')
FROM CTE T
GROUP BY HeaderData

Why correlated subquery doesn't allow two expressions - SQL Server

I have query like this:
select
objectid,
(select top 1 data_source, maxspeed
from SpeedLimitData3
where way_geometry.Filter(geography::STGeomFromText('POINT (' + cast(X as varchar(15)) + ' ' + cast(Y as varchar(15)) + ')', 4326)) = 1
order by way_geometry.STDistance(geography::STGeomFromText('POINT (' + cast(X as varchar(15)) + ' ' + cast(Y as varchar(15)) + ')', 4326))
)
from
testData
Why does the SQL Server throw this error?
Msg 116, Level 16, State 1, Line 8
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
I know that this means that I need to remove one of subquery's selected columns. But why when I have single row as subquery result and not several?
The syntax of a select clause in Transact-SQL allows a <select-list> made up of various entities. A correlated subquery used in a select clause is an expression and supplies the value for a single result column.
this will work, but will output same data in otr.* part of select.
You have to use related fields in testData and applied correlation
select objectid, otr.*
from testData
outer apply
(
select top 1 data_source, maxspeed
from SpeedLimitData3
where way_geometry.Filter(geography::STGeomFromText('POINT (' + cast(X as varchar(15)) + ' ' + cast(Y as varchar(15)) + ')', 4326)) = 1
order by way_geometry.STDistance(geography::STGeomFromText('POINT (' + convert(varchar(15),X) + ' ' + convert(varchar(15),Y) + ')', 4326))
) otr
If X & Y are fields in testData
select tD.objectid, otr.*
from testData tD
outer apply
(
select top 1 data_source, maxspeed
from SpeedLimitData3
where way_geometry.Filter(geography::STGeomFromText('POINT (' + convert(varchar(15),tD.X) + ' ' + convert(varchar(15),tD.Y) + ')', 4326)) = 1
order by way_geometry.STDistance(geography::STGeomFromText('POINT (' + convert(varchar(15),tD.X) + ' ' + convert(varchar(15),tD.Y) + ')', 4326))
) otr

SQL Stored Procedure How to Modify and Return the Result of an Executed Dynamic Query

I have created a stored procedure that returns a single string of concatenated fields. The issue is that some of these fields may be empty strings resulting in a string much like the below:
, Mendip Road, Farnborough, Hampshire, GU14 9LS
or even
, , Farnborough, Hampshire, GU14 9LS
I really want to strip off any leading commas but I'll only know this once the query has been executed. Is there a way of executing the query, pattern-matching the commas and then removing them before finally returning the modified string?
The query itself is as follows:
SET #SQLQuery = 'SELECT TOP 1 REPLACE((ISNULL(POI,'''') + '', '' + ISNULL(Name,'''') + '', '''
+ ' + ISNULL(Settlement,'''') + '', '' + ISNULL(Cou_Unit,'''') + '', '' + ISNULL(Postcode,'''')),'', , '', '', '')'
+ ' AS ClosestAddress FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY '
+ ' (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' * (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' + (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') * (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') ASC'
EXECUTE(#SQLQuery)
Concatenate the comma inside the ISNULL expression as follows:
ISNULL(POI + ', ','')
so your query will look like:
SET #SQLQuery = 'SELECT TOP 1 REPLACE((ISNULL(POI + '', '','''') + ISNULL(Name + '', '','''')'
+ ' + ISNULL(Settlement + '', '','''') + ISNULL(Cou_Unit + '', '','''') + ISNULL(Postcode,'''')),'', , '', '', '')'
+ ' AS ClosestAddress FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY '
+ ' (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' * (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' + (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') * (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') ASC'
I don't know if you need dynamic SQL for some other reason, but I think something like this should work (with no Dynamic SQL); if you're really sure you need Dynamic SQL for some other reason, then just refactor this idea into your Dynanmic Statement:
DECLARE #ClosestAddress VARCHAR(1000)
SELECT TOP 1
#ClosestAddress = ISNULL(POI + ', ','')
+ ISNULL(Name + ', ','')
+ ISNULL(Settlement + ', ','')
+ ISNULL(Cou_Unit + ', ', '')
+ ISNULL(Postcode,'')
--AS ClosestAddress
FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY (Longitude = 12.2132) * (Longitude = 12.2132) + (Latitude - 12.2132) * (Latitude - 12.2132) ASC
IF (RIGHT(#ClosestAddress, 2) = ', ')
RETURN SUBSTRING(#ClosestAddress, 0, LEN(#ClosestAddress))
ELSE
RETURN #ClosestAddress
Why this should work: Concatenating NULL + ', ' will result in an empty string. Then we check if the string ends with ', ', and if so we return everything but the last two characters.
You could do something like Replace all Comma with space and then do LTRIM and RTRIM and replace all space with comma.
Create table Data(name varchar(10),lastname varchar(10));
insert into Data values('','Doe');
insert into Data values('Jane','Doe');
insert into Data values('Jane','');
SELECT Replace(Rtrim(Ltrim(Replace(ISNULL(name,'') +',' + ISNULL(lastname,'') + ',',',',' '))),' ',',')
from Data
something like : http://sqlfiddle.com/#!3/6a6c6/1

Removing empty list elements from a sql coalesce string

I have a query that has this syntax
coalesce(cast([tb_groups].[f_member_id_creator] as varchar) + ',', '') + coalesce(cast([tb_groups].[f_member_id_officer1] as varchar) + ',','') + coalesce(cast([tb_groups].[f_member_id_officer2] as varchar) + ',', '') + coalesce(cast([tb_groups].[f_member_id_officer3] as varchar) + ',','') + coalesce(cast([tb_groups].[f_member_id_officer4] as varchar) + ',', '') + coalesce(cast([tb_groups].[f_member_id_officer5] as varchar),'') as admin_list
F_member_id_creator is always present in the db, however f_member_id_officer1 through 5 may be available in any combination.
For example, a returned value from the above statement might be
"25431,32663,,,,"
or "25431,,32663,,,"
or "25431,,,32663,,"
or "25431,,,,32663,"
etc.
What I need to do is tell SQL to remove the empty list elements and just return "25431,32663"
Any way to do this in SQL Server 2005?
Or better yet, have it not select the empty ordinal at all if its null or blank?
YOU got the result because [tb_groups].[f_member_id_creator], maybe, the empty instead of null. Try this:
coalesce(NULLIF(LTRIM(RTRIM(cast([tb_groups].[f_member_id_creator] as varchar))), '') + ',', '') + ...
If you agree that you haven't trailing and/or leading spaces you can omit LTRIM/RTRIM.
I slightly modified above code... I think it works... because it worked for me
COALESCE(CAST([tb_groups].[f_member_id_creator] as varchar), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer1] as varchar),','), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer2] as varchar),','), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer3] as varchar),','), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer4] as varchar),','), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer5] as varchar),','), '') as admin_list

Insert vs Update

I have a table where all the fields are declared as nvarchar. If I do an insert into the table all unicode characters come into the fields fine. But when I do an update I am losing some of the characters. Here is my udpate statement:
UPDATE TableII
SET LOCATION = CAST(( COALESCE([CITY], N'') + NCHAR(13) + NCHAR(10)
+ COALESCE([INSTALLATION], N'') + NCHAR(13)
+ NCHAR(10) + LEFT(LOCATION.LATLONG, 2) + N'°'
+ SUBSTRING(LOCATION.LATLONG, 3, 2) + N''''
+ SUBSTRING(LOCATION.LATLONG, 5, 2) + NCHAR(34)
+ N' ' + SUBSTRING(LOCATION.LATLONG, 7, 1)
+ N' ' + SUBSTRING(LOCATION.LATLONG, 8, 3)
+ N'°' + SUBSTRING(LOCATION.LATLONG, 11, 2)
+ N'''' + SUBSTRING(LOCATION.LATLONG, 13, 2)
+ NCHAR(34) + N' ' + SUBSTRING(LOCATION.LATLONG,
15, 1) ) AS NVARCHAR(MAX))
FROM TABLEII
INNER JOIN LOC ON TABLEII.REC = LOC.REC
INNER JOIN LOCATION ON LOC.LOCRECNUM = LOCATION.LOCRECNUM
WHERE ( LOC.LOCSEQ = '1' )
As you can see I have tried a variety of things to force the unicode characters to not be lost, but it does not work.
Any ideas why the insert works fine but this update does not?
Is the City column NVARCHAR? If not, the COALESCE will take that column as it's data type and use it, regardless of what you do with the rest of the code.

Resources