how to add condition to delete last character in sql query - sql-server

I have a table
ID | OSTag
2145 | BMV123456,BMV234567,BMV123789,BMV124654,BMV456234, BMV908567,
5437 | DAD676776,DAD989898,DAD787656,
5452 | DAD123456,
Query
SELECT DISTINCT bag2.PassengerID,
( SELECT bag1.OSTag +',' AS [text()] FROM REZP8OD01.dbo.Baggage bag1
WHERE bag1.PassengerID=bag2.PassengerID
ORDER BY bag1.PassengerID FOR XML PATH(''))[OSTag] FROM dbo.Baggage bag2
Now I want to add check condition into my sql query that if last item of column OSTag then remove character ','.
Output result like this:
ID | OSTag
2145 | BMV123456,BMV234567,BMV123789,BMV124654,BMV456234, BMV908567
5437 | DAD676776,DAD989898,DAD787656
5452 | DAD123456

SELECT DISTINCT
bag2.PassengerID
,STUFF(( SELECT ',' + bag1.OSTag AS [text()]
FROM REZP8OD01.dbo.Baggage bag1
WHERE bag1.PassengerID=bag2.PassengerID
ORDER BY bag1.PassengerID FOR XML PATH('')), 1,1,'') [OSTag]
FROM dbo.Baggage bag2
Or even better would be
SELECT bag2.PassengerID
,STUFF(( SELECT ',' + bag1.OSTag
FROM REZP8OD01.dbo.Baggage bag1
WHERE bag1.PassengerID=bag2.PassengerID
ORDER BY bag1.PassengerID
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'), 1,1,'') [OSTag]
FROM dbo.Baggage bag2
GROUP BY bag2.PassengerID
SQL Fiddle

You could do this a number of ways. Probably the easiest is using LEFT.
select LEFT(OSTag, len(OSTag) - 1)
I have to mention that storing delimited values in a single column violates 1NF and is a serious pain to deal with.

Related

Which concept i want use to get following output using SQL server 2012

My Table having following data's
ID | Name
--- | ---------
1 | Apple
2 | Microsoft
3 | Samsung and so on...
In my case, input is '1,2,3'.
And i need output is 'Apple,Microsoft,Samsung'.
SELECT STUFF((
SELECT ','+ Name
FROM MyTable
WHERE ID in (1, 2, 3)
FOR XML PATH('')
), 1, 1, '') AS Names
Result:
Apple,Microsoft,Samsung
You can do with XML PATH
SELECT
(
SELECT
T.Name + ', '
FROM
Tbl T
WHERE
Id in (1, 2, 3)
FOR XML PATH ('')
) DesiredOutput
Result looks like Apple, Microsoft, Samsung,
USE [Database Name]
SELECT COLUMN_NAME,*
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YourTableName'
As SQL server doesn't support input in runtime, you can either create a stored procedure and pass the input value while executing it. or just run the following query.
SELECT NAME
FROM MyTable
WHERE ID IN
(SELECT TOP 3 ID FROM MyTable ORDER BY ID)

Extraction queries with variable last part of the search term

I have a problem with an extraction query.
I want to extract all records that begin with exactly one name.
The problem:
Not always the end of the name is this extension;
When they are present, they have no fixed length.
Example:
TabNames
id | Name
1 | Mike
2 | Mike Nell-1
3 | Mike-2
4 | Robert-1
5 | Mike Rio-NN
6 | Mike-Orio-2
.....
Name searched for: 'Mike'
Desired outcome:
Mike, Mike-2
If interested, I use SQL Server.
How can I do?
You can do this with FOR XML. You will have update the Table Names, Columns Names and Where Statement in both select statements. This is a variation of this Concatenation Script.
SELECT DISTINCT
SUBSTRING(
(
SELECT ', '+ T1.Name AS [text()]
FROM dbo.TabNames T1
WHERE T1.Name LIKE 'Mike%'
ORDER BY T1.Name
FOR XML PATH ('')
), 3, 8000) AS Names
FROM
dbo.TabNames T2
WHERE
T2.Name LIKE 'Mike%'

Join tables by column names, convert string to column name

I have a table which store 1 row per 1 survey.
Each survey got about 70 questions, each column present 1 question
SurveyID Q1, Q2 Q3 .....
1 Yes Good Bad ......
I want to pivot this so it reads
SurveyID Question Answer
1 Q1 Yes
1 Q2 Good
1 Q3 Bad
... ... .....
I use {cross apply} to acheive this
SELECT t.[SurveyID]
, x.question
, x.Answer
FROM tbl t
CROSS APPLY
(
select 1 as QuestionNumber, 'Q1' as Question , t.Q1 As Answer union all
select 2 as QuestionNumber, 'Q2' as Question , t.Q2 As Answer union all
select 3 as QuestionNumber, 'Q3' as Question , t.Q3 As Answer) x
This works but I dont want to do this 70 times so I have this select statement
select ORDINAL_POSITION
, COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = mytable
This gives me the list of column and position of column in the table.
So I hope I can somehow join 2nd statement with the 1st statement where by column name. However I am comparing content within a column and a column header here. Is it doable? Is there other way of achieving this?
Hope you can guide me please?
Thank you
Instead of Cross Apply you should use UNPIVOT for this query....
SQL Fiddle
MS SQL Server 2008 Schema Setup:
CREATE TABLE Test_Table(SurveyID INT, Q1 VARCHAR(10)
, Q2 VARCHAR(10), Q3 VARCHAR(10), Q4 VARCHAR(10))
INSERT INTO Test_Table VALUES
(1 , 'Yes', 'Good' , 'Bad', 'Bad')
,(2 , 'Bad', 'Bad' , 'Yes' , 'Good')
Query 1:
SELECT SurveyID
,Questions
,Answers
FROM Test_Table t
UNPIVOT ( Answers FOR Questions IN (Q1,Q2,Q3,Q4))up
Results:
| SurveyID | Questions | Answers |
|----------|-----------|---------|
| 1 | Q1 | Yes |
| 1 | Q2 | Good |
| 1 | Q3 | Bad |
| 1 | Q4 | Bad |
| 2 | Q1 | Bad |
| 2 | Q2 | Bad |
| 2 | Q3 | Yes |
| 2 | Q4 | Good |
If you need to perform this kind of operation to lots of similar tables that have differing numbers of columns, an UNPIVOT approach alone can be tiresome because you have to manually change the list of columns (Q1,Q2,Q3,etc) each time.
The CROSS APPLY based query in the question also suffers from similar drawbacks.
The solution to this, as you've guessed, involves using meta-information maintained by the server to tell you the list of columns you need to operate on. However, rather than requiring some kind of join as you suspect, what is needed is Dynamic SQL, that is, a SQL query that creates another SQL query on-the-fly.
This is done essentially by concatenating string (varchar) information in the SELECT part of the query, including values from columns which are available in your FROM (and join) clauses.
With Dynamic SQL (DSQL) approaches, you often use system metatables as your starting point. INFORMATION_SCHEMA exists in some SQL Server versions, but you're better off using the Object Catalog Views for this.
A prototype DSQL solution to generate the code for your CROSS APPLY approach would look something like this:
-- Create a variable to hold the created SQL code
-- First, add the static code at the start:
declare #SQL varchar(max) =
' SELECT t.[SurveyID]
, x.question
, x.Answer
FROM tbl t
CROSS APPLY
(
'
-- This syntax will add to the variable for every row in the query results; it's a little like looping over all the rows.
select #SQL +=
'select ' + cast(C.column_id as varchar)
+ ' as QuestionNumber, ''' + C.name
+ ''' as Question , t.' + C.name
+ ' As Answer union all
'
from sys.columns C
inner join sys.tables T on C.object_id=T.object_id
where T.name = 'MySurveyTable'
-- Remove final "union all", add closing bracket and alias
set #SQL = left(#SQL,len(#SQL)-10) + ') x'
print #SQL
-- To also execute (run) the dynamically-generated SQL
-- and get your desired row-based output all at the same time,
-- use the EXECUTE keyword (EXEC for short)
exec #SQL
A similar approach could be used to dynamically write SQL for the UNPIVOT approach.

Joining a table based on comma separated values

How can I join two tables, where one of the tables has multiple comma separated values in one column that reference an id in another column?
1st table
Name | Course Id
====================
Zishan | 1,2,3
Ellen | 2,3,4
2nd table
course id | course name
=======================
1 | java
2 | C++
3 | oracle
4 | dot net
Maybe this uglyness, I have not checked results:
select names.name, courses.course_name
from names inner join courses
on ',' + names.course_ids + ',' like '%,' + cast(courses.course_id as nvarchar(20)) + ',%'
First of all your Database structure is not normalized and should have been. Since it is already set up this way , here's how to solve the issue.
You'll need a function to split your string first:
CREATE FUNCTION SPLIT_STRING(str VARCHAR(255), delim VARCHAR(12), pos INT) RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1), delim, '');
Then you'll need to create a view in order to make up for your structure:
CREATE VIEW database.viewname AS
SELECT SPLIT_STRING(CourseID, ',', n) as firstField,
SPLIT_STRING(CourseID, ',', n) as secondField,
SPLIT_STRING(CourseID, ',',n) as thirdField
FROM 1stTable;
Where n is the nth item in your list.
Now that you have a view which generates your separated fields, you can make a normal join on your view, just use your view like you would use a table.
SELECT *
FROM yourView
JOIN table1.field ON table2.field
However since I don't think you'll always have 3 values in your second field from your first table you'll need to tweak it a little more.
Inspiration of my answer from:
SQL query to split column data into rows
and
Equivalent of explode() to work with strings in MySQL
SELECT f.name,s.course_name FROM table1 AS f
INNER JOIN table2 as s ON f.course_id IN (s.course_id)
Use the Below Query For Solution
Select * from table_2 t2 INNER JOIN table_1 t1 on t1.Course Id = t2.course id

T-SQL concatenate rows into string

I'm trying to use a sub query on a select statement for a field value but I can't seem to figure out the correct syntax. I want to pull a list of company names and as a field for that query, I want to select all the employees for that company.
Any ideas on what I'm doing wrong? The error I get is
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS
T-SQL code:
SELECT
company_name,
company_type,
(SELECT
employee_firstname, employee_lastname
FROM
tblemployees
WHERE
tblemployees.company_id = tblCompanies.company_id) as employees
FROM
tblCompanies
Desired output:
Company Name | Company Type | Employees
----------------------------------------------------------
Test Co | Construction | Bob Smith, Jack Smith, etc
You'll need to concatenate the first and last names using FOR XML PATH or a similar solution. More details on the various methods here.
SELECT DISTINCT
c1.company_name,
c1.company_type,
STUFF((SELECT
', ' + c2.employee_firstname + ' ' + c2.employee_lastname
FROM
tblCompanies c2
WHERE
c1.company_id = c2.company_id
ORDER BY
employee_lastname, employee_firstname
FOR XML PATH(''), TYPE).value('.', 'varchar(max)'), 1, 1, '')
FROM tblCompanies c1
SQL Fiddle

Resources