Issue with GROUP_CONCAT and output to csv - mysql

I am facing an issue with GROUP_CONCAT and exporting the results to csv.
Consider the following table
Search Results
with columns search Id | Description | Votes | search category
and consider the following data in the table
1|java, beans|2|java
2|serialization|3| java
3|jquery| 1|javascript
4|mysql joins|5| database
I need the output in the following format
Search Category| description1 | description 2 | votes 1 | votes 2
java |java,beans | serialization | 2 | 3
javascript |jquery | | 1
database | mysqljoins | | 5
I need to output this data into a csv file.
I have written the following query
select category, GROUP_CONCAT(description), GROUP_CONCAT(votes) from search_results group by search_category into outfile '/tmp/out.csv' fields terminated by ',' enclosed by '"' lines terminated by '\n';
However, following are the issues
-The above query returns one column each for description and votes which displays the comma separated values . I need separate columns for each of the values(as shown in the desired output)
- for the category javascript, the output is returned in the format
javascript|jquery|5<br/>
I will need the out put in the format
javascript|jquery| | 5| |
There should be a placeholder for the empty values

SELECT
s1.search_category
, s1.description AS description1
, ISNULL(s2.description, '') AS description2
, s1.votes AS votes1
, ISNULL(s2.votes, '') AS votes2
FROM search_results AS s1
LEFT OUTER JOIN search_results AS s2 ON s2.search_category = s1.search_category
WHERE s1.search_id < s2.search_id
INTO OUTFILE ...
LEFT JOINing the table to its self will give you the second column if there is one. If there isn't one, the values will be NULL and the ISNULL will return spaces (or whatever else you want).
If there are more than 2 rows with the same search_category, you will get more than one row in the output which might not be what you're after.

Related

Remove All Backslash into string in MySQL query

I have this type of string
'160f7a4a-766a-4c23-a155-8bd3f7389f77\', \'63233bfc-b663-4c73-890b-00a48d79c4dc'
In one column and I want like
'160f7a4a-766a-4c23-a155-8bd3f7389f77','63233bfc-b663-4c73-890b-00a48d79c4dc'
This type of result in MySQL
i have to perform query like
SELECT * FROM kapp_staging.kols where `kol_id` in (select REPLACE(json_id,'\'',"'") FROM kapp_staging.news_items
where `id` = '991'))
in where in clause i have subquery and in subquery
i geting
'160f7a4a-766a-4c23-a155-8bd3f7389f77\', \'63233bfc-b663-4c73-890b-00a48d79c4dc'
this type of value
so i need to remove \ from value so my where in query work fine.
i have data like:
Kols table
| id | kol_id | name | data |
|----|---------------------------------------- |---------| ------|
| 1 |160f7a4a-766a-4c23-a155-8bd3f7389f77 | balwant | data |
| 2 |63233bfc-b663-4c73-890b-00a48d79c4dc | vikram | data |
news items
| id | json_id | data |
|----|-----------------------------------------------------------------------------------------|---------|
| 991 | {'\160f7a4a-766a-4c23-a155-8bd3f7389f77\','\160f7a4a-766a-4c23-a155-8bd3f7389f77\'} | data |
I tried many ways but didn't get this response.
Thanks in Advance : )
The backslashes aren't in the data, they're just used to escape the quotes when inserting into the table. So you don't need to remove them.
However, you can't use IN to match values in a comma-delimited list, you need to use FIND_IN_SET(); see Search with comma-separated value mysql
You also need to remove the quotes and curly braces before you can use FIND_IN_SET().
SELECT DISTINCT k.*
FROM kols AS k
JOIN news_items AS n
ON FIND_IN_SET(k.kol_id,
REPLACE(REPLACE(REPLACE(json_id, '{', ''), '}', ''), "'", ''))
DEMO
Things would be much easier if you normalized your data and put the list of IDs into a separate table with one row per ID.

Mysql - How do I avoid group by but still with concat and group concat I would need to combine multiple columns and rows results

I have something like in table
mysql> select uuid , short-uuid FROM sampleUUID WHERE identifier ="test123";
+--------------------------------------+-------------+
| uuid | short-uuid |
+--------------------------------------+-------------+
| 11d52ebd-1404-115d-903e-8033863ee848 | 8033863ee848 |
| 22b6f783-aeaf-1195-97ef-a6d8c47261b1 | 8033863ee848 |
| 33c51085-ccd8-1119-ac37-332510a16e1b | 332510a16e1b |
+--------------------------------------+-------------+
I would be needing a result like (grouped all in single row, single value w.r.t uuid and short-uuid being same)
| uuidDetails
+----------------------------------------------------------------------------------------------------------------+-------------+
| 11d52ebd-1404-115d-903e-8033863ee848,22b6f783-aeaf-1195-97ef-a6d8c47261b1|8033863ee848&&33c51085-ccd8-1119-ac37-332510a16e1b| 332510a16e1b |
+----------------------------------------------------------------------------------------------------------------+-------------+
(basically grouping uuid and short uuid in a single row from multiple rows and columns)
I know this can be achieved by select GROUP_CONCAT(uuid)FROM sampleUUID WHERE identifier ="test123" group by short-uuid;
but i don't wanna use group by here because that give multiple rows, i would need all in one row .
I have tried with below stuffs but failed to get the the results in single row
select ANY_VALUE(CONCAT_WS( '||',CONCAT_WS('|',GROUP_CONCAT(uuid) SEPARATOR ','),short-uuid)) )as uuidDetails from sampleUUID
where identifier ="test123";
this resulted like below with not appending short-uuid properly (there is only 1 short uuid appended here,Actually it needs to be grouped first 2 uuids with 1 short(because same short-uuid) uuid and 3rd uuid with other short uuid)
| uuidDetails
+----------------------------------------------------------------------------------------------------------------+-------------+
| 11d52ebd-1404-115d-903e-8033863ee848,22b6f783-aeaf-1195-97ef-a6d8c47261b1,33c51085-ccd8-1119-ac37-332510a16e1b| 332510a16e1b |
+----------------------------------------------------------------------------------------------------------------+-------------+
which is not i expected
Any help here will be appreciated . Thank you
Use nested queries.
SELECT GROUP_CONCAT(result ORDER BY result SEPARATOR '&&') AS uuidDetails
FROM (
SELECT CONCAT(GROUP_CONCAT(uuid ORDER BY uuid SEPARATOR ','), '|', short_uid) AS result
FROM sampleUUID
WHERE identifier = 'test123'
GROUP BY short_uid
) AS x
NOTE: If there is no requirement for ordering of the UUID values, we can use ORDER BY inside the GROUP_CONCAT aggregates to make the result more deterministic, so the query will return just one of a number of possible results given the same data e.g. return aa,bb|1&&cc|3 rather than bb,aa|1&&cc|3 or cc|3&&aa,bb|1 or cc|3&&bb,aa|1.

MySQL - query to get specific result

I have started learning MySQL and I'm stuck on a case.
I have the following table:
id | value
1 | abc
1 | def
2 |
2 |
3 | pqr
3 |
4 |
4 | xyz
5 |
Please note the empty values beside numeric int denotes empty strings.
Problem statement: I need to get those ids which if formed into a group would only have empty strings attached to it. Example here would be ids: 2, 5
Explanation: id = 2 appears twice both with empty strings and hence included. id = 5 appears once and have one empty string, thus included. id = 3 is not included since one of its instance has got non-empty value i.e. "pqr"
I am stuck with the query:
SELECT * FROM t1 GROUP BY id;
But this gives a wrong result.
Could you please help me out? What should be the query to get ids = 2, 5. I am sorry for the table formatting.
SELECT DISTINCT t1.id
FROM t1
LEFT JOIN t1 t1d ON t1d.id = t1.id AND t1d.value <> ''
WHERE t1d.id IS NULL
without GROUP BY and HAVING = one happy database!
You can achieve the expected outcome with conditional counting compared to counting of all rows within a group:
select id from t1
group by id
having count(*)=count(if(`value`='',1,null))
count(*) returns the number of records with the corresponding id. count(if(value='',1,null)) return the number of such records, where the value field is an empty string.
Using below query you will get your desired output.
select id
from test_empty
group by id
having TRIM(TRAILING ',' FROM group_concat(value))=""
By group_concat(value) output will concatenated value by comma for all the ids.
By using TRIM(TRAILING ',' FROM group_concat(value)) trailing comma can be removed
By using having we can place condition on group by that only id with all blank value will be retrieved.
An empty string will always be "less than" any non-empty string, so this should do the trick:
select id from t1
group by id
having max(value) = ''

MySQL Query : Match comma separated value with column containing comma separted string

I have a user table containing a column(say interests) with comma separated interest ids as a value.
e.g.
user interests
A 12,13,15
B 10,11,12,15
C 9,13
D 10,12
Now, I have a string with comma separated values as "13,15".
I want to fetch the users who has the interest 13,15 from above table means it should return the user A, B & C as user A contains both interest(13,15), user B matched the interest with 15 & user matched the interest with 13.
what will be the SQL as I have a lots of users in my table.
It can be done with regexp as #1000111 said, but with more complicated regexp. Look at this, for example:
(^|,)(13|15)(,|$)
This will not match 13 from 135, or 1 from 13 and so on. For example, for number 13 this will match next strings:
1,13,2
13,1,2
1,13
13,2
13
But will not match these
1,135,2
131,2
1,113
And this is query:
SET #search = '13,15';
SELECT *
FROM test
WHERE interests REGEXP CONCAT('(^|,)(', REPLACE(#search, ',', '|'), ')(,|$)')
If you want to get the result based on loose matching then you can follow this query:
Loose matching means interests like 135,151 would also appear while searching for '13,15'.
SET #inputInterest := "13,15";
SELECT
*
FROM userinterests
WHERE interests REGEXP REPLACE(#inputInterest,',','|');
For the given data you will get an output like below:
| ID | user | interests |
|----|------|-------------|
| 1 | A | 12,13,15 |
| 2 | B | 10,11,12,15 |
| 3 | C | 9,13 |
SQL FIDDLE DEMO
EDIT:
If you want result based on having at least one of the interests exactly then you can use regex as #Andrew mentioned in this answer:
Here's I've modified my query based on his insight:
SET #inputInterest := "13,15";
SELECT
*
FROM userinterests
WHERE interests REGEXP CONCAT('(^|,)(', REPLACE(#inputInterest, ',', '|'), ')(,|$)')
SEE DEMO OF IT
Note:
You need to replace the #inputInterest variable by your input string.
Suggestion:
Is storing a delimited list in a database column really that bad?

How to parse CSV and import to MYSQL issue

I am really stuck at this moment.. I searched and researched and I did not find anything similar, so maybe what I want is not doable.
I have a .xls file in this format
|contact| col1 |col2 | col3 |
---------------------------------
|name1 | info1 |info2 | info3 |
|address1| | | |
|phone1 | | | |
| | | | |
|name2 | | | |
|address2| info1 |info2 | info3 |
|phone2 | | | |
| | | | |
|name_n | info1 | info2| info3 |
|addres_n| | | |
|phone_n | | | |
----------------------------------
So I was thinking about creating a table which will be called contact, and another called info. The table contact will contain id(primary key),name,address and phone as fields. And another table with id (primary key) , name (foreign key), col1,col2 and col3. In such a way that if I want to know the details of the name (in table info ) I could go to the other table and see all the values.
So I researched about how to import this xls format file and the optimal solution will be convert the xls file to a csv file delimited by comma.
Therefore, the code which I was thinking to use is (after converting to csv- delimited by comma) the following:
But the point is that I just want to to the following:
"Info" Table : name1,info1,info2,info3.
"Contact" Table : name1,address,phone1.
Related to "Info" Table
LOAD DATA INFILE '/home/username/myfile.csv'
INTO TABLE numbers FIELDS TERMINATED BY ';'
LINES STARTING BY '-' TERMINATED BY '\r\n'
IGNORE 1 LINES
(contact,col1,col2,col3);
It is ok when I'm filling the table because I just have to add a '-' at the beginning of the row which I want to fill into the table (the row which contains a non-empty field.)
Related to "Contact" table:
It is being difficult since, if I want to take just the column of contact I will have to add some symbol and then operate. Well, I was thinking in add an '*' (for instance) at the beggining of name1 and another one at the end of phone1 for defining the boundaries of the LINE. But I want to define also the fields, which will be a ';' as well. However, the algorithm of LOAD DATA INFILE takes the empty fields also. And I just want to take the fields which contains something different than "empty string"/"null"/. So the question is if I would be able to say something to avoid the empty string. Because as a I read in the MySQL DOC this is written:
An empty field value is interpreted different from a missing field:
For string types, the column is set to the empty string.
For numeric types, the column is set to 0.
For date and time types, the column is set to the appropriate “zero” value for >the type. See Section 11.3, “Date and Time Types”.
But it does not say anything about avoid it. (I mean, If is an empty value, then pass the the next field and evaluate again until find a non-empty value)
I am asking that because with my idea of face it It will fill a row like that :
Name1,null,null,null,address1,null,null,null,phone1 and so on.
Any ideas?
focusing just on Contact for now, what if your excel spreadsheet has 4 columns where columnA is action with N for all rows. You change it to Y if you want it ultimately in your real table.
Your csv now has 4 columns:
action, Name, address, phone
You load data infile into a worktable. Now you have your data in (some not actually wanted), and an insert into select where action='y' will finish it up, into your real table from worktable.
In Excel you can create two worksheets, the first with contact data, the second with info data. Those sheets can be separately exported as csv files.