I have a table structure that looks like this:
ID String
-----------
1 A
1 Test
1 String
2 Dear
2 Person
I need the final output to look like this:
ID FullString
--------------------
1 A, Test, String
2 Dear, Person
I am really lost on how to approach this... I looked on a couple examples online but they seemed to be VERY complex... this seems like it should be a real easy problem to solve in sql.
Thank you for all assistance!
SELECT ID, GROUP_CONCAT(String) AS FullString
FROM TABLE
GROUP BY ID
There are additional parameters available for GROUP_CONCAT to control sequence and separation. GROUP_CONCAT is MySQL specific.
Related
Suppose i have a table with a string and i want to create an aggregation of this table by grouping different string in a 'category'.
In order to understand to which category assign each string I have a list of possibilities that I could sum up as it follows:
CASE WHEN string = 'aaa' THEN 'cat_aaa'
CASE WHEN string = 'bbb' THEN 'cat_bbb'
[...]
CASE WHEN string LIKE '%abc%' THEN 'cat_abc'
Now, the list may be very huge and may needs update, so I don't want to make an infinite list of CASE WHEN. I'd like instead to have a table with the string used for the comparison and the corresponding category.
So let's suppose to have a first table with all the strings:
TABLE A
=======
string
--------
aaa
bbb
aaa
aaa
aaa
dabc
fabc
------
and another table
TABLE B
=======
string_comparison | category
aaa | cat_aaa
bbb | cat_bbb
%abc% | cat_abc
If they were all = condition, i could have just joined on the two strings. However, depending on the type of string_comparison, I may need to perform a LIKE comparison.
Do you have any fresh idea on how to solve this situation? I wouldn't like to join the two tables on a LIKE basis because of performances. Is there the possibility to use regular expressions on the string to solve this?
I am using redshift.
A like without a wildcard is effectively the same as a =, and any reasonable optimizer should handle it properly, so I wouldn't try to overthink things and just try joining witha like:
SELECT category, COUNT(*)
FROM a
JOIN b ON string LIKE string_comparison
GROUP BY category
If you're really concerned about the performance of the like operator you could try to check if the string_comparison doesn't have a wildcard in it and short-circuit it out, but I doubt it would be any faster than just using like directly:
SELECT category, COUNT(*)
FROM a
JOIN b ON (POSITION('%' IN string_comparison) > 0 AND
POSITION('_' IN string_comparison) > 0 AND
string LIKE string_coparison) OR
string = string_comparison
GROUP BY category
Note: You didn't tag the question with the RDBMS you are using, so I gave an example using Postgresql's position function. Other RDBMSs should have functions with the same functionality, although their names may differ.
So we have a table with a field that contains strings.
These strings can contain wildcards.
For example:
id | name
---+----------------
1 | thomas
2 | san*
3 | *max*
Now I want to select from that table with respect to these wildcards.
For example something like this:
SELECT * FROM table WHERE name = 'sandra'.
That SELECT should fetch the record with ID = 2 from my table.
Note that it would be ok to use % instead of * as the wildcard character in the table.
Any way to achieve this in OpenSQL?
You can use wildcards, just the sign (like Matecki said), is %.
Take a look here:
https://scn.sap.com/thread/1418148
Additionally You could create and use a ranges table in the where clause. If You do not know, what it is, and how it can be done, just tell me. Populate the ranges table like this: OPTION = CP, SIGN = I, LOW = san.
Ok for You?
UPDATE:
I was wrong and changed the answer
I have a problem with trying to remove a row of data based on a LIKE match in sql. I'm working with SQL Server 2005.
I have a table (#Containers) which holds information like below:-
PMBID DEPT
------ ---------
248057 5,8
249799 5,6,8
249800 5
249941 1,5
249942 1,4,15,16
249943 1,4,5
249945 4
249946 4
249947 4
249966 8,16,23
249967 5,6,8,16
Both columns are string, I need a query to be able to remove rows based on departments, for example if the PMBID has department 1,11,23, or 31 in it, it needs to be removed from the table. So with this logic PMBID's...
249941
249942
249943
249966
would be removed.
So how do I do this (well) in SQL seen as my column is string?
I've been writing queries such as...
DELETE FROM #Containers WHERE (Dept LIKE '%1%' OR Dept LIKE '%11%' OR Dept LIKE '%23%' OR Dept LIKE '%31%')
Obviously this statement doesn't work as it catches departments like 15, and 16, so for example PMBID
249967
would be included when it shouldn't as it's not explicitly a 1,11,23, or 31 (or a combination of these).
Is this possible with a string column? Can we use the delimiter somehow to improve the query?
I'll stop now as risk of over-complicating the query, please let me know if you need any further information.
The commas-in-the-list searching problem. Put commas around DEPT and around the values in the string:
DELETE FROM #Containers
WHERE (','+Dept+',' LIKE '%,1,%' OR
','+Dept+',' LIKE '%,11,%' OR
','+Dept+',' LIKE '%,23,%' OR
','+Dept+',' LIKE '%,31,%')
It is bad practice to store data in a comma delimited string, but this will work for department 1 as an example:
DELETE FROM #Containers
WHERE Dept LIKE '%,1'
OR Dept LIKE '1,%'
OR Dept LIKE '%,1,%'
You have to force commas into the criteria to exclude 1 from catching 11 and so on.
Might be cleaner to use a function that splits the string into individual values.
Here a good article on the subject:
http://www.sqlperformance.com/2012/07/t-sql-queries/split-strings
Suppose I have a SQL query like this:
SELECT
tickets.TicketNumber, history.remarks
FROM
AT_DeviceReplacement_Tickets tickets
INNER JOIN
AT_DeviceReplacement_Tickets_History history
ON tickets.TicketNumber = history.TicketNumber;
I get a table like this in repsonse:
ticketNumber | remarks
-------------+------------
1 | "Hello, there is a problem."
1 | "Did you check the power cable?
1 | "We plugged it in and now it works. Thank you!"
2 | "Hello, this is a new ticket."
Suppose that I want to write a query that will concatenate the remarks for each ticket and return a table like this:
ticketNumber | remarks
-------------+------------
1 | "Hello, there is a problem.Did you check the power cable?We plugged it in and now it works. Thank you!"
2 | "Hello, this is a new ticket."
Yes, in the real code, I've actually got these sorted by date, among other things, but just for the sake of discussion, how would I edit the above query to get the result I described?
Have a look at the following questions:
Can I Comma Delimit Multiple Rows Into One Column?
Is it possible to concatenate column values into a string using CTE?
The cleanest solution to this problem is DB dependent. Lentine's links show very ugly solutions for Oracle and SQL Server and a clean one for MySQL. The answer in PostgreSQL is also very short and easy.
SELECT ticket_number, string_agg(remarks, ', ')
FROM
AT_DeviceReplacement_Tickets tickets
INNER JOIN
AT_DeviceReplacement_Tickets_History history
ON tickets.Ticket_Number = history.Ticket_Number
GROUP BY tickets.ticket_number;
(Note you have both ticket_number and TicketNumber in your sample code.)
My guess is that Oracle and SQL Server either (1) have a similar aggregate function or (2) have the capability of defining your own aggregate functions. [For MySQL the equivalent aggregate is called GROUP_CONCAT.] What DB are you using?
The string below I have to call three times using sql.
String: JAN###PIET###HENK
The first call shoudl return:
JAN
The second call:
PIET
The third:
HENK
So we could use the ### as separator but it could be that the string is:
JAN###PIET only. Still all three calls will be done where
call 1 returns:
JAN
call 4 returns:
PIET
cal three return:
<>
Same could happen for string JAN only.
I hope this explanation is sufficient for someone to help me with this case.
Thanks in advance.
Regards,
Ryni
if you're using sql 2005, adapt this post to your needs:
Split Funcin - SQL 2005
It sounds to me like you are asking for a split function that maintains state like an enumerator. You don't actually want that. That could be very bad potentially.
I'd recommend a split string function (in sql server, they're called table valued functions). If you do that, worst case scenario is you have to loop over the table result. In any event, you can find the function here: http://dpatrickcaldwell.blogspot.com/2008/08/table-valued-function-to-split-strings.html
Your usage would look like this:
SELECT *
FROM dbo.SplitString('JAN###PIET###HENK', '###')
-- PartId Part
-- ----------- --------
-- 1 JAN
-- 2 PIET
-- 3 HENK
SELECT *
FROM dbo.SplitString('JAN###PIET###HENK', '###')
WHERE PartId = 2
-- PartId Part
-- ----------- --------
-- 2 PIET
every possible SQL Server split string method with detailed pro and cons:
http://www.sommarskog.se/arrays-in-sql.html