This question already has answers here:
Splitting the full name and writing it to another table in SQL Server 2008
(2 answers)
Closed 9 years ago.
How would I go about splitting one column that has the first, last and middle name. To there own separate columns in a SQL Server 2008 query?
The column is called NAME
NAME(char(25),null)
Mctasrren ,David Max
Cressler ,Patti L
Basil ,Vessen Eddie
Chapplestait ,Victoy
this is what i've used so far my main issue is the middle name. or if someone has a better way to shorten the first name code.
--last name code
left([NAME],charindex(' ,',[NAME]))
-first name code
substring([NAME],charindex(',',[NAME])+1,charindex(' ',substring([NAME],charindex(',',[NAME])+1,25-charindex(',',[NAME])+1)))
Do you want to split it into columns as part of a result set, create computed columns on the table, or actually update the schema to have the data split in the source?
In any case the basic nuts and bolts can be done by either:
Use a combination of CHARINDEX, SUBSTRING, and LEFT or RIGHT to find commas or spaces and split around that. If you sure you data will always be 'L_NAME ,F_NAME M_NAME_OR_INITIAL' that will pretty easy. I am actually I surprised I didn't find an similar question here near the top of a google search, but there is an example of similar from SQLServerCentral.
Use a RegEx via the CLR, which can be more robust if there is any variety in the data. If you are familiar with RegEx this should be a straight forward parse. Again, a simplified example can found on MSDN.
Whatever you choose, you'll probably quickly run into names that don't easily follow that format. In that case you want to build more logic into a function handle different types of names.
Related
I want to create 3 new columns with their names reffering to some date varibales and this is not possible to write them like this. So the first column name should be YEAR2022, 2nd column YEAR2021 and 3rd column YEAR2020.
Can you please give me an idea how to write this?
select column1*2 as CONCAT('YEAR',YEAR(DATEADD(YY,0,GETDATE()))),
column1*3 as CONCAT('YEAR',YEAR(DATEADD(YY,-1,GETDATE()))),
column1*4 as CONCAT('YEAR',YEAR(DATEADD(YY,-2,GETDATE()))) FROM table1
The error that I get is:
Incorrect syntax near 'YEAR'.
As I mentioned in my comment, an alias cannot be an expression, it has to be a literal. As such the expressions you have tried to use are not allowed and generate syntax errors.
Normally, this sort requirement is the sign of a design flaw, or that you're trying to do something that should be in the presentation in the SQL layer. I'm going to assume the latter here. As a result, instead you should use static names for the columns, and then in your presentation layer, control the name of the columns there, so that when they are presented to the end user they have the names you want (for today that would be YEAR2022, YEAR2021 and YEAR2020). Then your query would just look like this:
select column1*2 AS ThisYear,
column1*3 AS YearPrior,
column1*4 AS Year2Prior
FROM dbo.table1;
How you change the names of the columns in your presentation layer is a completely different question (we don't even know what language you are using to write your application). If you want to ask about that, I suggest asking a new question (only if after you've adequately researched the problem and failed to find a solution), so that we can help you there.
Note that Though you can achieve a solution via dynamic SQL, I would strongly suggest it is the wrong solution here, and thus why I haven't given an answer providing a demonstration.
My question right now is whether something can be done or not, as a result, no code has been included in this question. If it can be done what is the correct phrase that I can query and research this further.
I am working with a customer database where the request has been made that if a specific word is used in the comments field, that word is replaced or hidden when the query is used report and viewed using SSRS / Report Builder.
I had also wondered if even an expression can be written to hide or mask that word, and this would then be used in the tablix field that is used on the report.
Any suggestions are appreciated.
The database is Microsoft SQL 2016 with SSRS 2017 and Report Builder 2016.
If there is a specific word, then the answer is simple. You can just use replace(). In fact, you can add this into the table:
alter table t add safe_comments as (replace(comments, '<bad word>', 'XXXXXXX'));
You can extend this to a handful of hard-coded words by nesting replace() values.
I suspect, however, that your problem is that you have a fairly long list of words that you want to replace. If that is the case, such a simple solution is not going to work.
It is possible in SQL Server to remove a list of words, stored in a table, from a given comment. That requires a recursive CTE (or a user-defined function). This probably has acceptable performance for returning a single record or a handful of records. However, for scanning the entire table, it would probably be too slow.
I have to write a select statement following the following pattern:
[A-Z][0-9][0-9][0-9][0-9][A-Z][0-9][0-9][0-9][0-9][0-9]
The only thing I'm sure of is that the first A-Z WILL be there. All the rest is optional and the optional part is the problem. I don't really know how I could do that.
Some example data:
B/0765/E 3
B/0765/E3
B/0764/A /02
B/0749/K
B/0768/
B/0784//02
B/0807/
My guess is that I best remove al the white spaces and the / in the data and then execute the select statement. But I'm having some problems writing the like pattern actually.. Anyone that could help me out?
The underlying reason for this is that I'm migrating a database. In the old database the values are just in 1 field but in the new one they are splitted into several fields but I first have to write a "control script" to know what records in the old database are not correct.
Even the following isn't working:
where someColumn LIKE '[a-zA-Z]%';
You can use Regular Expression via xQuery to define this pattern. There are many question in StackOverFlow that talk about patterns in DB2, and they have been solved with Regular Expressions.
DB2: find field value where first character is a lower case letter
Emulate REGEXP like behaviour in SQL
I have a table containing a series of survey responses, structured like this:
Question Category | Question Number | Respondent ID | Answer
This seemed the most logical storage for the data. The combination of Question Category, Question Number, and Respondent ID is unique.
Problem is, I've been asked for a report with the Respondent ID as the columns, with Answer as the rows. Since Answer is free-text, the numeric-expecting PIVOT command doesn't help. It would be great if each row was a specific Question Category / Question Number pairing so that all of the information is displayed in a single table.
Is this possible? I'm guessing a certain amount of dynamic SQL will be required, especially with the expected 50-odd surveys to display.
I think this task should be done by your client code - trying to do this transposing on SQL side is not very good idea. Such SQL (even if it can be constructed) will likely be extremely complicated and fragile.
First of all, you should count how many distinct answers are there - you probably don't want to create report 1000 columns wide if all answers are different. Also, you probably want to make sure that answers are narrow - what if someone gave really bad 1KB wide answer?
Then, you should construct your report (would that be HTML or something else) dynamically based on results of your standard, non-transposed SQL.
For example, in HTML you can create as many columns as you want using <th>column</th> for table header and <td>value</td> for data cell - as long as you know already how many columns are going to be in your output result.
To me, it seems that the problem is the number of columns. You don't know how many respondents there are.
One idea would be to concatenate the respondent ids. You can do this in SQL Server as:
select distinct Answer,
(select cast(RespondentId as varchar(255))+'; '
from Responses r2
where r2.Answer = r.Answer
for xml path ('')
) AllResponders
from Responses r
(This is untested so may have syntax errors.)
If reporting services or excel power pivot are possibilities for the report then they could both probably accomplish what you want easier than a straight sql query. In RS you can use a tablix, and in power pivot a pivot table. Both avoid having to define your pivot columns in an sql pivot statement, and both can dynamically determine the column names from a tabular result set.
I suppose I have always naively assumed that scalar functions in the select part of a SQL query will only get applied to the rows that meet all the criteria of the where clause.
Today I was debugging some code from a vendor and had that assumption challenged. The only reason I can think of for this code failing is that the Substring() function is getting called on data that should have been filtered out by the WHERE clause. But it appears that the substring call is being applied before the filtering happens, the query is failing.
Here is an example of what I mean. Let's say we have two tables, each with 2 columns and having 2 rows and 1 row respectively. The first column in each is just an id. NAME is just a string, and NAME_LENGTH tells us how many characters in the name with the same ID. Note that only names with more than one character have a corresponding row in the LONG_NAMES table.
NAMES: ID, NAME
1, "Peter"
2, "X"
LONG_NAMES: ID, NAME_LENGTH
1, 5
If I want a query to print each name with the last 3 letters cut off, I might first try something like this (assuming SQL Server syntax for now):
SELECT substring(NAME,1,len(NAME)-3)
FROM NAMES;
I would soon find out that this would give me an error, because when it reaches "X" it will try using a negative number for in the substring call, and it will fail.
The way my vendor decided to solve this was by filtering out rows where the strings were too short for the len - 3 query to work. He did it by joining to another table:
SELECT substring(NAMES.NAME,1,len(NAMES.NAME)-3)
FROM NAMES
INNER JOIN LONG_NAMES
ON NAMES.ID = LONG_NAMES.ID;
At first glance, this query looks like it might work. The join condition will eliminate any rows that have NAME fields short enough for the substring call to fail.
However, from what I can observe, SQL Server will sometimes try to calculate the the substring expression for everything in the table, and then apply the join to filter out rows. Is this supposed to happen this way? Is there a documented order of operations where I can find out when certain things will happen? Is it specific to a particular Database engine or part of the SQL standard? If I decided to include some predicate on my NAMES table to filter out short names, (like len(NAME) > 3), could SQL Server also choose to apply that after trying to apply the substring? If so then it seems the only safe way to do a substring would be to wrap it in a "case when" construct in the select?
Martin gave this link that pretty much explains what is going on - the query optimizer has free rein to reorder things however it likes. I am including this as an answer so I can accept something. Martin, if you create an answer with your link in it i will gladly accept that instead of this one.
I do want to leave my question here because I think it is a tricky one to search for, and my particular phrasing of the issue may be easier for someone else to find in the future.
TSQL divide by zero encountered despite no columns containing 0
EDIT: As more responses have come in, I am again confused. It does not seem clear yet when exactly the optimizer is allowed to evaluate things in the select clause. I guess I'll have to go find the SQL standard myself and see if i can make sense of it.
Joe Celko, who helped write early SQL standards, has posted something similar to this several times in various USENET newsfroups. (I'm skipping over the clauses that don't apply to your SELECT statement.) He usually said something like "This is how statements are supposed to act like they work". In other words, SQL implementations should behave exactly as if they did these steps, without actually being required to do each of these steps.
Build a working table from all of
the table constructors in the FROM
clause.
Remove from the working table those
rows that do not satisfy the WHERE
clause.
Construct the expressions in the
SELECT clause against the working table.
So, following this, no SQL dbms should act like it evaluates functions in the SELECT clause before it acts like it applies the WHERE clause.
In a recent posting, Joe expands the steps to include CTEs.
CJ Date and Hugh Darwen say essentially the same thing in chapter 11 ("Table Expressions") of their book A Guide to the SQL Standard. They also note that this chapter corresponds to the "Query Specification" section (sections?) in the SQL standards.
You are thinking about something called query execution plan. It's based on query optimization rules, indexes, temporaty buffers and execution time statistics. If you are using SQL Managment Studio you have toolbox over your query editor where you can look at estimated execution plan, it shows how your query will change to gain some speed. So if just used your Name table and it is in buffer, engine might first try to subquery your data, and then join it with other table.