SQL Server : combine two rows into one - sql

I want to write a query which will display the following result
FROM
ID Contract# Market
1 123kjs 40010
1 123kjs 40011
2 121kjs 40098
2 121kjs 40099
TO
ID Contract# Market
1 123kjs 40010,40011
2 121kjs 40098,40099

Try out this query, I use GROUP_CONCAT to turn column fields into 1 row field.
Also notice that you should rename the FROM clause with the name of your table.
SELECT ID,Contract#, GROUP_CONCAT(Market SEPARATOR ',')
FROM nameOfThatTable GROUP BY ID;

Try this out. I used PIVOT to solve it.
SELECT
ID,
Contract#,
ISNULL(CONVERT(varchar,[40010]) + ',' + CONVERT(varchar,[40011]),
CONVERT(varchar,[40098]) + ',' + CONVERT(varchar,[40099])) AS Market FROM
( SELECT * FROM ContractTable) AS A
PIVOT(MIN(Market) FOR Market IN ([40010],[40011],[40098],[40099])) AS PVT
ORDER BY ID

You can use ', ' + CAST(Market AS VARCHAR(30)) in sub-query and join Id and Contract# of sub-query with outer query to get values of Market as Comma Separated Values for each Id and Contract#.
SELECT DISTINCT ID,Contract#,
SUBSTRING(
(SELECT ', ' + CAST(Market AS VARCHAR(30))
FROM #TEMP T1
WHERE T2.Id=T1.Id AND T2.Contract#=T1.Contract#
FOR XML PATH('')),2,200000) Market
FROM #TEMP T2
Click here to view result
Note
.........
If you want to get CSV values for Id only, remove T2.Contract#=T1.Contract# from sub-query.

Related

How to combine the column values from the same table with condition in sql select query

I want to combine the Currency field by comparing Config and Product Column. If both field is repeated with duplicate values but different currency, the combine the currency into single row as you see in the screenshot.
I tried the code like
Select DISTINCT LC.Config, LC.Product, CONCAT(LC.Currency,',',RC.Currency) as Currencies FROM [t_LimitCurrency] LC INNER JOIN [t_LimitCurrency] RC ON LC.[Config] = RC.[Config] AND LC.Product = RC.Product
Please let me know, how to write select statement for this scenario.
Below Code should do the trick. I am using XML Path but you can use String_AGG in latest version of sql server
select distinct Config,Product,
STUFF((SELECT ' ,' + CAST(Currency AS VARCHAR(max)) [text()]
FROM (
SELECT Currency
FROM Yourtable b
WHERE a.Config=b.Config and a.product=b.product
) ap
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') Currency
from Yourtable a
EDIT 1 : for latest version of sql server code should be like below
select distinct Config,Product,
(SELECT
STRING_AGG(CONVERT(NVARCHAR(max),Currency), ',')
FROM YourTable b WHERE a.Config=b.Config and a.product=b.product)
Currency
from Yourtable a

Pivot one column with multiple rows into to one concatenated row

I need to prepare a list of emails tat can be copy and pasted into the email field (2.5k).
I have one column with one email address in each row.
I need the end result to look like:
email1#test.com; email2#test.com; email3#test.com
Select *
from(
Select email, 1 as num
FROM tabl1
WHERE b.stu_cde = 1 ) e
Pivot( max(email)
for num in ([1]) )as pv
Try this. Instead of pivot use stuff to get your result. For more details about pivot please find this link PIVOT.
select Stuff( (select ';' + email from tabl1 for xml path('')),1,1,'') as Result

SQL Server : Breaking Comma Delimited String and matching values in a table

I am using SQL Server and have a "tags" column that has a string of of comma-separated tags. Is there a way to break the string up and place in another table and have them match to be able to easily see liked tags?
Row 1:
3years_andmore,access_ccc,access_sdl,associate_iii,ccc_tickets,desoto_counter,phone_call__property_tax,ticketing,trainer
Row 2:
3years_andmore,access_ccc,access_sdl,associate_iii,ccc_tickets,desoto_counter,phone_call__dmv,ticketing,trainer
Row 3:
5_minutes,access_ccc,access_sdl,associate_ii,ccc_tickets,desoto_counter,lessthan_3years,phone_call__operations___title_by_mail_inquiry,trainer
Row4:
access_ccc,access_sdl,associate_ii,ccc_customer_request_manager_other,ccc_tickets,desoto_counter,lessthan_3years,phone_call__associate_requesting_manager__customer_requesting_mr_brierton,trainer
There is no real order and not the same tags in field but is there a way to at least sort into a new table and break them up and match to see what tickets have the same tags?
SELECT
[id],
[url],
[external_id],
[type],
[subject],
[description],
[priority],
[status],
[recipient],
[requester_id],
[submitter_id],
[assignee_id],
[organization_id],
[group_id],
[collaborator_ids],
[forum_topic_id],
[problem_id],
[has_incidents],
[due_at],
[tags],
[via],
[custom_fields],
[satisfaction_rating],
[sharing_agreement_ids],
[followup_ids],
[ticket_form_id],
[created_at],
[updated_at],
[channel]
FROM
[Brierton].[dbo].[Tickets]
WHERE
created_at BETWEEN '2017-11-01' AND '2018-08-23'
AND ',' + tags + ',' LIKE '%,' + 'ccc_tickets' + ',%'
Since version 2016 there's a built in string_split() function. To get the tags per ticket in a "more relational way" you could use:
SELECT t.id,
x.value
FROM tickets t
CROSS APPLY (SELECT value
FROM string_split(t.tags, ',')) x;
From there you could aggregate to get the most used tags.
SELECT x.value,
count(*)
FROM tickets t
CROSS APPLY (SELECT value
FROM string_split(t.tags, ',')) x
GROUP BY x.value
ORDER BY count(*) DESC;
db<>fiddle

Find duplicates in SQL table, list multiple instances

I'm trying to list the multiple instances of tbldoc.[docid] from tbldoc where tbldoc.[filename] occurs more than once, id like them seperated by comma and grouped by [filename]
this code works great to find duplicates:
SELECT cast([filename] as varchar(max)),
COUNT(cast([filename] as varchar(max)))
FROM tbldoc
GROUP BY cast([filename] as varchar(max))
HAVING ( COUNT(cast([filename] as varchar(max))) > 1 )
but when i try adding [docid] i get an error:
Column 'tbldoc.DocID' is invalid in the select list because it is not
contained in either an aggregate function or the GROUP BY clause.
this is what i am trying:
SELECT [docid], cast([filename] as varchar(max)),
COUNT(cast([filename] as varchar(max)))
FROM tbldoc
GROUP BY cast([filename] as varchar(max))
HAVING ( COUNT(cast([filename] as varchar(max))) > 1 )
I have no idea how to get all of the [docid]s to list seperated by commas, I'm a a pretty new user when it comes to sql.
this is the output i would like to see:
[docids]|[filemame]|[instances]
12345,12346| excelfile.xls | 3
Thanks ahead of time for the help guys/gals! =)
Iyosha,
You need to join your first result set back to your full table to get the DocIDs. I'll take the CAST() as read to save some typing.
;with CountedFiles as
(
SELECT
filename,
COUNT(filename) as Total
FROM tbldoc
GROUP BY filename
HAVING COUNT(filename) > 1
)
select
cf.filename,
cf.Total,
td.DocID
from CountedFiles as cf
inner join tbldoc at td
on td.filename = cf.filename;
This will return one DocId, one filename and the count per row. You can then follow Adam's link to turn this into a comma list.

ORDER BY items must appear in the select list if SELECT DISTINCT is specified

I added the columns in the select list to the order by list, but it is still giving me the error:
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
Here is the stored proc:
CREATE PROCEDURE [dbo].[GetRadioServiceCodesINGroup]
#RadioServiceGroup nvarchar(1000) = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT rsc.RadioServiceCodeId,
rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
FROM sbi_l_radioservicecodes rsc
INNER JOIN sbi_l_radioservicecodegroups rscg
ON rsc.radioservicecodeid = rscg.radioservicecodeid
WHERE rscg.radioservicegroupid IN
(select val from dbo.fnParseArray(#RadioServiceGroup,','))
OR #RadioServiceGroup IS NULL
ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
END
Try this:
ORDER BY 1, 2
OR
ORDER BY rsc.RadioServiceCodeId, rsc.RadioServiceCode + ' - ' + rsc.RadioService
While they are not the same thing, in one sense DISTINCT implies a GROUP BY, because every DISTINCT could be re-written using GROUP BY instead. With that in mind, it doesn't make sense to order by something that's not in the aggregate group.
For example, if you have a table like this:
col1 col2
---- ----
1 1
1 2
2 1
2 2
2 3
3 1
and then try to query it like this:
SELECT DISTINCT col1 FROM [table] WHERE col2 > 2 ORDER BY col1, col2
That would make no sense, because there could end up being multiple col2 values per row. Which one should it use for the order? Of course, in this query you know the results wouldn't be that way, but the database server can't know that in advance.
Now, your case is a little different. You included all the columns from the order by clause in the select clause, and therefore it would seem at first glance that they were all grouped. However, some of those columns were included in a calculated field. When you do that in combination with distinct, the distinct directive can only be applied to the final results of the calculation: it doesn't know anything about the source of the calculation any more.
This means the server doesn't really know it can count on those columns any more. It knows that they were used, but it doesn't know if the calculation operation might cause an effect similar to my first simple example above.
So now you need to do something else to tell the server that the columns are okay to use for ordering. There are several ways to do that, but this approach should work okay:
SELECT rsc.RadioServiceCodeId,
rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
FROM sbi_l_radioservicecodes rsc
INNER JOIN sbi_l_radioservicecodegroups rscg
ON rsc.radioservicecodeid = rscg.radioservicecodeid
WHERE rscg.radioservicegroupid IN
(SELECT val FROM dbo.fnParseArray(#RadioServiceGroup,','))
OR #RadioServiceGroup IS NULL
GROUP BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
Try one of these:
Use column alias:
ORDER BY RadioServiceCodeId,RadioService
Use column position:
ORDER BY 1,2
You can only order by columns that actually appear in the result of the DISTINCT query - the underlying data isn't available for ordering on.
Distinct and Group By generally do the same kind of thing, for different purposes... They both create a 'working" table in memory based on the columns being Grouped on, (or selected in the Select Distinct clause) - and then populate that working table as the query reads data, adding a new "row" only when the values indicate the need to do so...
The only difference is that in the Group By there are additional "columns" in the working table for any calculated aggregate fields, like Sum(), Count(), Avg(), etc. that need to updated for each original row read. Distinct doesn't have to do this... In the special case where you Group By only to get distinct values, (And there are no aggregate columns in output), then it is probably exactly the same query plan.... It would be interesting to review the query execution plan for the two options and see what it did...
Certainly Distinct is the way to go for readability if that is what you are doing (When your purpose is to eliminate duplicate rows, and you are not calculating any aggregate columns)
When you define concatenation you need to use an ALIAS for the new column if you want to order on it combined with DISTINCT
Some Ex with sql 2008
--this works
SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName
from SalesLT.Customer c
order by FullName
--this works too
SELECT DISTINCT (c.FirstName + ' ' + c.LastName)
from SalesLT.Customer c
order by 1
-- this doesn't
SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName
from SalesLT.Customer c
order by c.FirstName, c.LastName
-- the problem the DISTINCT needs an order on the new concatenated column, here I order on the singular column
-- this works
SELECT DISTINCT (c.FirstName + ' ' + c.LastName)
as FullName, CustomerID
from SalesLT.Customer c
order by 1, CustomerID
-- this doesn't
SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName
from SalesLT.Customer c
order by 1, CustomerID
You could try a subquery:
SELECT DISTINCT TEST.* FROM (
SELECT rsc.RadioServiceCodeId,
rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
FROM sbi_l_radioservicecodes rsc
INNER JOIN sbi_l_radioservicecodegroups rscg ON rsc.radioservicecodeid = rscg.radioservicecodeid
WHERE rscg.radioservicegroupid IN
(select val from dbo.fnParseArray(#RadioServiceGroup,','))
OR #RadioServiceGroup IS NULL
ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
) as TEST