Using coalesce to concatenate a variable character and lenght filled field [duplicate] - sql-server

This question already has answers here:
nvarchar concatenation / index / nvarchar(max) inexplicable behavior
(2 answers)
VARCHAR(MAX) acting weird when concatenating string
(1 answer)
Closed last year.
I have a query that selects values from two joined tables, one table has the value to join and another table has the "format" configuration.
SELECT #SegmentValue = COALESCE ( #SegmentValue +
CASE
WHEN el.FillFormat = 'RIGHT'
THEN LEFT ( val.CalculatedValue + REPLICATE(el.fillcharacter, el.Length) , el.Length)
ELSE LEFT ( val.CalculatedValue + REPLICATE(el.fillcharacter, el.Length) , el.Length)
END
,''
)
FROM EDI_Element el
INNER JOIN #EDI_Element_Values val ON
This query is having a very interesting behavior; as it is the variable that only has the very last value, so if I return 4 records like r1 , r2 r3 , r4 (I tested this by running the exact same query but with select * instead of the coalesce as I first suspected the joins) the variable will have a value of r4.
An interesting thing I found is that if I hardcode a value inside the replicate for example 100, the query works as expected.

Related

Why rows with NULL in column used in WHERE clause are omitted in results? [duplicate]

This question already has answers here:
Not equal <> != operator on NULL
(10 answers)
SQL Inner Join On Null Values
(8 answers)
How to use NULL or empty string in SQL
(17 answers)
WHERE clause using values that could be NULL
(2 answers)
Is there a way to simplify a NULL compare of 2 values
(2 answers)
Closed 12 months ago.
Is that bug in SQL server or I don't know something?
I have table "Items" of structure:
Id - (PRIMARY) int Auto Increment
FinalStatus - tinyint (NULLABLE)
With data it looks like:
Id
Status
1
NULL
2
NULL
3
NULL
4
1
5
2
I'm trying to list all records that their Status is different than 2:
SELECT * FROM [Items] WHERE [Status] != '2'
SELECT * FROM [Items] WHERE [Status] != 2
SELECT * FROM [Items] WHERE [Status] NOT LIKE '2'
SELECT * FROM [Items] WHERE [Status] NOT IN (2)
All these queries returns only one row:
Id
Status
4
1
However if I use query:
SELECT * FROM [Items] WHERE [Status] IS NULL
In that case I get all NULL rows displayed - but only them.
Since NULL is not the same as 2 or any other number, I feel confused with the result of the queries. However there is difference how I designed this table and all previous.
This time I've forgot to allow nulls on creation, and I've used SQL studio to do it afterwards. IMHO this is the reason of the trouble, but I have no idea what exactly it can be.
I could delete the table and recreate it, but would like to learn something.
Thanks for all kind help.
Is that bug in SQL server or I don't know something
Well, it's not a bug.
Think of NULL as a placeholder for "Unknown" and it will be clearer.
If I ask you to find me all the rows where the value is not 2 then you cannot return any NULL (unknown) value since you do not know that it is NOT 2.
If you want to include NULLs then the criteria should be
where value != 2 or value is null;
Use this query
SELECT * FROM [Items] WHERE ISNULL([Status], 0) != 2

Split and get second row as value [duplicate]

This question already has answers here:
Using T-SQL, return nth delimited element from a string
(14 answers)
Closed 4 years ago.
I'm using below query to split the names as shown below:
select value from STRING_SPLIT('Name1~Name2~Name3' , '~' );
How to get second name i.e, Name2, without using WHERE condition?
Note: Names can be dynamic
Try PARSENAME function
SELECT PARSENAME( REPLACE('Name1~Name2~Name3','~','.'),2)
output
Name2
PARSENAME Returns the specified part of an object name. The parts of an object that can be retrieved are the object name, owner name,
database name, and server name.
Instead of using STRING_SPLIT you can convert your string to XML and then use .value to retrieve the 2nd element:
SELECT CAST('<t>' + REPLACE('Name1~Name2~Name3' , '~','</t><t>') + '</t>' AS XML).value('/t[2]','varchar(50)')
Try below code:
SELECT TOP 1 T.* FROM
(SELECT TOP 2 * FROM STRING_SPLIT('Name1~Name2~Name3' , '~' ) ORDER BY value ASC) AS T
ORDER BY value DESC;

T SQL - splitting column into two columns after first '-' [duplicate]

This question already has answers here:
T-SQL split string based on delimiter
(9 answers)
Closed 6 years ago.
Got dbo where i need to split it into two, after first '-' character. Working on SSMS 2014
example in spreadsheet:
example
PartNumber holds data which needs to be break up.
Part - Need to have all characters before first '-'
Number - need to have all characters after first '-'
Any help appreciated
thanks
You need LEFT and RIGHT. And to find the location where you want to split to LEFT and RIGHT, us CHARINDEX.
Maybe something like this?
SELECT parts.PartID as ID,
Part = (SELECT TOP 1 value FROM STRING_SPLIT(parts.PartNumber, '-')),
Number = (SELECT value FROM STRING_SPLIT(parts.PartNumber, '-') LIMIT 1 OFFSET 1),
FROM dbo.PartsTable parts
You could try this.
SELECT
PartNum
, REPLACE(LEFT(PartNum, CHARINDEX('-', PartNum)),'-', '') as 'PartNum First'
, REPLACE(SUBSTRING(PartNum,CHARINDEX('-', PartNum), LEN(PartNum)), '-','') as 'PartNum Second'
FROM Part
The query above splits the PartNum string when it finds '-', it then replaces it with a blank space so you have the result you expected.
I tried it and it works. Hope it's useful to you.
Declare #YourTable table (PartNumber varchar(50))
Insert Into #YourTable values
('HHY-12-1800-2'),
('FC-P-41-4')
Select PartNumber
,Part = Left(PartNumber,CharIndex('-',PartNumber)-1)
,Number = Substring(PartNumber,CharIndex('-',PartNumber)+1,Len(PartNumber))
From #YourTable
Returns
PartNumber Part Number
HHY-12-1800-2 HHY 12-1800-2
FC-P-41-4 FC P-41-4

Concatenating Column Values into a Comma-Separated string [duplicate]

This question already has answers here:
How to use GROUP BY to concatenate strings in SQL Server?
(22 answers)
Closed 7 years ago.
I have a table which looks like the following:
EventProfileID ParamName ParamValue
1 _CommandText usp_storedproc_1
2 _CommandText usp_storedproc_2
2 _CommandText usp_storedproc_3
2 _CommandText usp_storedproc_100
3 _CommandText usp_storedproc_11
3 _CommandText usp_storedproc_123
What I would like my output to be is the following:
EventProfileID ParamValue
1 usp_storedproc_1
2 usp_storedproc_2, usp_storedproc_3, usp_storedproc_100
3 usp_storedproc_11, usp_storedproc_123
However I am having some bother. If I do a select on one of the event profile ID's I can get an output using the following logic:
SELECT LEFT(c.ParamValue, LEN(c.ParamValue) - 1)
FROM (
SELECT a.ParamValue + ', '
FROM DP_EventProfileParams AS a
WHERE a.ParamName = '_CommandText'
and a.EventProfileId = '13311'
FOR XML PATH ('')
) c (paramvalue)
However that just gives me the output for one EventProfileID and also I would like the EventProfileID as part of the output.
Can anyone give me any pointers in the right direction into how I can expand my code to include this and allow the code to be dynamic so that I can show all EventProfileID's?
Thanks
You can do it this way:
select distinct a.EventProfileID,
stuff((select ','+ ParamValue)
from DP_EventProfileParams s
where s.EventProfileID = a.EventProfileID
for XML path('')),1,1,'')
from DP_EventProfileParams a
You were on the right track with for XML path. STUFF function makes it easier to achieve what you want.
The original query does not work because it uses simple subquery (works only for one specific id)
To make it work for all ids you can use XML + STUFF inside correlated subquery:
Many queries can be evaluated by executing the subquery once and
substituting the resulting value or values into the WHERE clause of
the outer query. In queries that include a correlated subquery (also
known as a repeating subquery), the subquery depends on the outer
query for its values. This means that the subquery is executed
repeatedly, once for each row that might be selected by the outer
query.
SELECT DISTINCT
EventProfileID,
[ParamVaues] =
STUFF((SELECT ',' + d2.ParamValue
FROM #DP_EventProfileParams d2
WHERE d1.EventProfileID = d2.EventProfileID
AND d2.ParamName = '_CommandText'
FOR XML PATH('')), 1, 1, '')
FROM #DP_EventProfileParams d1
ORDER BY EventProfileID;
LiveDemo
I strongly suggest reading Concatenating Row Values in Transact-SQL

The column 'TRANSACTION_EVENT_ID' was specified multiple times for 'YY' [duplicate]

This question already has answers here:
SQL 2005 - The column was specified multiple times
(5 answers)
Closed 7 years ago.
I have written a query like this:
SELECT
YY.ACCOUNT_ID,
YY.TRANSACTION_EVENT_ID
FROM
(SELECT *
FROM dbo.TRANSACTION TE
JOIN dbo.FUND_TRANSACTION FT
ON TE.TRANSACTION_EVENT_ID = FT.TRANSACTION_EVENT_ID
JOIN ACCOUNT A
ON FT.ACCOUNT_ID = A.ACCOUNT_ID) AS YY
and getting error like this:
The column 'TRANSACTION_EVENT_ID' was specified multiple times for 'YY'
Checked this : SQL The column 'Id' was specified multiple times
However, the issue is not resolved. What am I doing wrong?
The issue is with the SELECT *. Since the same column names can be repeat in the selection.
Explicitly mention the column names. The below query will work.
SELECT YY.ACCOUNT_ID, YY.TRANSACTION_EVENT_ID
FROM ( SELECT FT.ACCOUNT_ID, FT.TRANSACTION_EVENT_ID
FROM dbo.[TRANSACTION] TE
JOIN dbo.FUND_TRANSACTION FT ON TE.TRANSACTION_EVENT_ID = FT.TRANSACTION_EVENT_ID
JOIN ACCOUNT A ON FT.ACCOUNT_ID = A.ACCOUNT_ID
) AS YY
You have to specify from which table TRANSACTION_EVENT_ID you want to select. You have to specify column list with aliases / table names instead of *. Something like:
SELECT
YY.ACCOUNT_ID,
YY.TRANSACTION_EVENT_ID
FROM
(SELECT A.ACCOUNT_ID,
TE.TRANSACTION_EVENT_ID
FROM dbo.TRANSACTION TE
JOIN dbo.FUND_TRANSACTION FT
ON TE.TRANSACTION_EVENT_ID = FT.TRANSACTION_EVENT_ID
JOIN ACCOUNT A
ON FT.ACCOUNT_ID = A.ACCOUNT_ID) AS YY

Resources