Pivot one column with multiple rows into to one concatenated row - sql

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

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

SQL Query - Copy Data into One Field

I have a SQL database and I am writing a query:
SELECT *
FROM Consignments
INNER JOIN OrderDetail
ON Consignments.consignment_id = OrderDetail.consignment_id
INNER JOIN UserReferences
ON OrderDetail.record_id = UserReferences.record_id
WHERE Consignments.despatch_date = '2020-04-23'
Within the first column is:consignment_id [this is from the Consignments table]In the final column is:senders_reference [this is from the UserReferences table]
Now - the issue I have is - that when I am running the query to pick up all consignments for a particular date - it is displaying multiple rows (with duplicated consignment_id) when there are multiple senders references within the database.
If there is one senders reference number - then there is only 1 row.
This makes sense - because within the front-end for the database the user can enter 1 or more senders references.
Now - what I would like to do is to amend my query for the resulting data to only display 1 row for all consignments and if there are multiple senders reference numbers - to have them within the one field, separated by commas.
Is this doable from the query stage?
Or if not - after export, is it possible to develop a bat file to do the same thing?
For reference - this is what I mean - this is the result I am getting at the moment:
This is what I need:
You can use older style with the help of for xml :
select t.consignment_id,
stuff((select ', ' +convert(varchar(255), t1.sender_reference)
from table t1
where t1.consignment_id = t.consignment_id
for xml path('')
), 1, 1, ''
) as senders_reference
from (select distinct consignment_id from table t) t;
Edit : You can use CTE :
with cte as (
<your query>
)
select t.consignment_id,
stuff((select ', ' +convert(varchar(255), t1.sender_reference)
from cte t1
where t1.consignment_id = t.consignment_id
for xml path('')
), 1, 1, ''
) as senders_reference
from (select distinct consignment_id from cte t) t;
You seem to want to use the STRING_AGG function.
This answer covers it nicely
ListAGG in SQLSERVER

SQL Server : combine two rows into one

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.

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