SQLYOG - SQL - Merging two columns into 1 column - mysql

I have two columns displaying the same type of information but not necessarily the same data. Although some of the data overlaps each column may/may not contain information that will also include NULL values. Like so:
Company ID | Company Name | Company ID | Company Name
-----------+--------------+------------+-------------
1 | A | 1 | A
2 | B | NULL | NULL
NULL | NULL | 3 | C
I am trying to merge columns 1 and 2 to columns 3 and 4, respectively, so that I have two columns that look like this:
Company ID | Company Name
-----------+-------------
1 | A
2 | B
3 | C
Looking at similar stackoverflow questions, I have doubt this may be done easily. Is this possible? Please, let me know!
Anything helps.

As you don't seem to be around to answer questions for clarification right now, let's go ahead.
It seems, you do actually have the four columns in question in a single table - but than, there should be no duplicate column names. Once they are unique, the following should work:
UPDATE SomeTable
SET company_ID_1 = IFNULL(company_ID_1, company_ID_2)
, company_Name_1 = IFNULL(company_Name_1, company_Name_2)
WHERE
company_ID_1 IS NULL
OR
company_Name_1 IS NULL
;
If the presented is actually the output of a join, you could replace the same by:
SELECT
IFNULL(SomeTable1.company_ID, SomeTable2.company_ID) company_ID
, IFNULL(SomeTable1.company_Name, SomeTable2.company_Name) company_Name
FROM SomeTable1
LEFT JOIN SomeTable2
ON SomeTable1.company_ID = SomeTable2.company_ID
UNION ALL
SELECT
IFNULL(SomeTable1.company_ID, SomeTable2.company_ID) company_ID
, IFNULL(SomeTable1.company_Name, SomeTable2.company_Name) company_Name
FROM SomeTable1
RIGHT JOIN SomeTable2
ON SomeTable1.company_ID = SomeTable2.company_ID
WHERE SomeTable1.company_ID IS NULL
ORDER BY company_ID
;
See it in action: SQL Fiddle
Please comment, if and as this requires adjustment / further detail.

Related

For each set of keywords in one table, find all matching hits in a second table

Disclaimer: I'm using MySQL with 2 tables. So far I've found solutions to my issue when individual groups are queried one at a time using IN() but nothing that allows me to do the whole table at once without looping over multiple queries.
I have two tables:
CREATE TABLE WordGroups (
wgId int NOT NULL AUTO_INCREMENT,
groupId int NOT NULL,
word varchar(255) NOT NULL,
PRIMARY KEY (wgId)
);
Which keeps track of groups of keywords, word to groupId, and
CREATE TABLE ArticleWords (
awId int NOT NULL AUTO_INCREMENT,
articleId int NOT NULL,
word varchar(255) NOT NULL,
PRIMARY KEY (awId)
);
which keeps track of the key words within an article.
I am attempting to build a single query which can take the groups of words, and return for each group all articles which contain AT LEAST all of those words.
I realize if I look for one group at a time in a single query this is very simple, however I can't seem to figure out how to make a single query result in the set of all matching subsets.
For example imagine that the two tables have the following data:
WordGroups
groupId | word
-----------------
1 | B
1 | A
2 | C
2 | E
3 | F
ArticleWords
articleId | word
-----------------
1 | A
1 | C
1 | B
2 | C
3 | A
3 | B
3 | F
4 | C
4 | E
4 | F
The resulting query would return:
groupId | articleId
1 | 1
1 | 3
2 | 4
3 | 3
3 | 4
Since those articles contain at least all the words from those groups.
I've attempted an intersection of the two tables using an inner join but that matches incomplete groups of words resulting in the row:
groupId | articleId
2 | 2
Showing up in the result all because Article 2 contains the word "C". I'm open to ideas as I've dabbled in less serious MySQL but this has been eluding me all week.
Any help is much appreciated. I'm at the point where I'm wondering if I'm trying to make SQL do something it isn't meant to do. I have a very long query which works for WordGroups up to 6 words but it is very exact and not scalable, this query would need to work for any size WordGroup to be feasible.
Thank you for reading!
Here is one method, uses group_concat() for the comparison:
select wg.groupId, aw.articleId
from articlewords aw join
wordgroups wg
on wg.word = aw.word join
(select wg.groupId, group_concat(wg.word order by word) as words
from word_groups wg
group by wg.groupId
) wgw
on wgw.groupId = wg.groupid
group by aw.articleid, wgw.words
having group_concat(aw.word order by aw.word) = wgw.words;
Here is a SQL Fiddle.

mysql merge rows with no unique rows

I need help in merging rowns into column in sql:
Table:
|TopologyType | TopologyName | Name |
| 1 | oneway | client1 |
| 1 | oneway | client2 |
| 2 | proxy | client1 |
| 2 | proxy | proxy1 |
| 2 | proxy | client2 |
Output:
| 1 | oneway | client1 | NULL | client2 |
| 2 | proxy | client1 | proxy | client2 |
In case you don't need all of the output fields to be in columns you could use GROUP_CONCAT
Example query
SELECT `t`.`TopologyType`,`t`.`TopologyName`,GROUP_CONCAT(DISTINCT(`tt`.`Name`)) as `name` from `test` `t`
left join `test` `tt`
ON `t`.`TopologyType`=`tt`.`TopologyType`
GROUP BY `t`.`TopologyName`;
Output
TopologyType TopologyName name
1 oneway client1,client2
2 proxy client1,proxy1,client2
view this example in SQL fiddle
Oof, you're a bit ropey on detail so don't expect this answer to work without some adjustment. Let me present you some sample data:
Name, Class, Score
john, math, 70
james, math, 75
john, english, 48
james, english, 69
Desired output:
name, mathscore, englishscore
john, 70, 48
james, 75, 69
Pivoting query for mysql (doesn't support PIVOT command)
SELECT
name,
MAX(CASE WHEN class = 'math' THEN score END) as mathscore
MAX(CASE WHEN class = 'english' THEN score END) as englishscore
FROM
grades
GROUP BY
name
If you want to know more about how it works, then run it without the GROUP BY and without the MAX functions:
SELECT
name,
CASE WHEN class = 'math' THEN score END as mathscore
CASE WHEN class = 'english' THEN score END as englishscore
FROM
grades
And then bear in mind that MAX() will not consider nulls when doing its work, so it causes the rows to collapse to only those containing values
As an aside - see how i've phrased my answer in terms of giving a sample data and a desired output? Do please write your next SQL question more like that, including the SQL you tried
Edit:
OK, so just apply the pattern in my SQL, to your names. For me, the "name" was the fixed column, the "class" was the one being pivoted out into multiple columns. The general pattern is:
SELECT
fixedColumn1,
fixedColumn2
..
fixedColumnN,
MAX(CASE WHEN column_with_values_that_must_be_headers = a1_value_you_want_in_its_own_column THEN column_with_value_to_appear_as_data1) as column_header_name1,
MAX(CASE WHEN column_with_values_that_must_be_headers = a2_value_you_want_in_its_own_column THEN column_with_value_to_appear_as_data2) as column_header_name2,
...
MAX(CASE WHEN column_with_values_that_must_be_headers = aN_value_you_want_in_its_own_column THEN column_with_value_to_appear_as_dataN) as column_header_nameN
FROM
table
GROUP BY
fixedColumn1,
fixedColumn2
..
fixedColumnN,
Here's a partial; have a go at finishing it off - you'll learn way more about this technique put doing a bit of it, than just hanging around waiting for someone to give you the answer to paste in :)
SELECT
TopologyType,
TopologyName,
MAX(CASE WHEN name = 'client1' THEN name END) AS client1,
... --put more CASE WHENs here
FROM
table
GROUP BY
TopologyType,
TopologyName
The only slight difference between your query and my earlier examples is that I had one column that I wanted to be the header (the name of the class; english / maths) but another column to be the data (the test score of the person in that class) whereas you effectively want the name as the column header AND the data. It's ok though - just follow the pattern above, using the name column as the header and the data:
MAX(CASE WHEN name = 'client1' THEN name END) AS client1,
^^^^^^^^^^^^^^^^ ^^^^
column_header cell_data

NOT IN subquery gives 0 results

i'm not an mysqlologist but i have to deal with the following problem:
given a following table:
+-------+-----------+-------------+------+
| id | articleID | img | main |
+-------+-----------+-------------+------+
| 48350 | 4325 | scr426872xa | 1 |
| 48351 | 4325 | scr426872ih | 2 |
| 48352 | 4325 | scr426872jk | 2 |
| 48353 | 4326 | scr426882vs | 1 |
| 48354 | 4326 | scr426882ss | 2 |
| 48355 | 4326 | scr426882nf | 2 |
+-------+-----------+-------------+------+
each set of images of one distinct articleID should have one image set as main=1 and an unspecified number of images with main value of 2
Due to processing issues it can happen that there is no main=1 set for an image and i need to find the articleID where images with main=2 exist, but not with main=1.
By explaining it backwards it is easier to fomulate what my thinking process for the query is. My idea was to create a result set (subquery) by querying the table for articleID where main is "1". Then use that result to check which distinct articleID of a query where main=2 is not in the results of aforementioned (sub-)query. Basically "substracting" all matching articleID lines.
This should give basically the leftover of all main=2 lines which have no line with the same articleID where main=1
SELECT DISTINCT articleID
FROM img_table WHERE main = 2
AND articleID
NOT IN (SELECT articleID FROM img_table WHERE main = 1 );
I get no result when I know for a fact that there are some. There is surely something I'm doing wrong. I hope my problem is explained in a way that not only me know what I want :)
Given your problem description, it looks like you're actually looking for NOT EXISTS to check for rows that don't have a matching row in the subselect. Note that you do have to add the article id to the where clause in the subselect:
SELECT DISTINCT articleID
FROM img_table t1
WHERE main = 2
AND NOT EXISTS
(SELECT articleID
FROM img_table t2
WHERE main = 1
AND t2.articleID = t1.articleID);
I think your current solution should work too, but maybe you didn't show all the data. For the data you specified, the query would indeed return 0 rows, because all articleIDs have at least one main=1 and a main=2 image.
One important thing to remember: the subquery must not return any NULL value, otherwise NOT IN won't work properly. So if articleID is nullable, make sure your subselect looks like this:
(SELECT articleID FROM img_table WHERE main = 1 and articleID IS NOT NULL)
I didn't find any issue in your query, Please add some data where article id having only main 2. Your query checking both article ID contains main 1,2. ie why you not getting any result.

MySQL incremental columns

I have a table like below:
ID|Prototype_A|Prototype_B|Prototype_C|Prototype_D|
---------------------------------------------------
1 |Fast381A |Blue4812 | Green7181 | White4812 |
---------------------------------------------------
2 |Slow841C |Orange8312 | null | null |
---------------------------------------------------
3 |Plane281K | null | null | null |
---------------------------------------------------
I need my query to return all non null prototypes for that ID.
so for example:
1 : Fast381A,Blue4812,Green7181,White4812
2 : Slow841C,Orange8312
3 : Plane281K
Is there a way to wildcard select all columns like select(Prototype_*) or should I setup my table in a different format?
For example I've been taught this type of structure is bad practice:
ID|Prototypes|
---------------------------------------------------
1 |Fast381A,Blue4812,Green7181,White4812
---------------------------------------------------
2 |Slow841C,Orange8312
---------------------------------------------------
3 |Plane281K
---------------------------------------------------
A SQL query returns a fixed set of columns. If you want to combine the non-NULL values into a single column, I would recommend concat_ws():
select id,
concat_ws(',', Prototype_A, Prototype_B, Prototype_C, Prototype_D)
from t;
This ignores the NULL values. The query returns two columns, one is a list of prototypes.
And, the answer to your question is "Yes". You should consider changing your data structure. Having multiple columns storing the same thing, with just an index identifying them usually means that you want a separate table, with one row per id and per prototype.
EDIT:
You want a table like this:
create table ModelPrototypes (
ModelProtypeId int primary key auto_increment,
ModelId int not null,
ProtoTypeChar char(1),
Prototype varchar(255)
);
Then you would populate it with values like:
1 A Fast381A
1 B Blue4812
1 C Green7181
1 D White4812
I'm not sure if PrototypeChar is really needed, but the information is in your table.
There's no way to wildcard select columns.
What you could do:
Setup your table as
ID, Prototype_type, Prototype_name
Then use GROUP_CONCAT:
SELECT id, GROUP_CONCAT(Prototype_name SEPARATOR ',')
FROM table GROUP BY Prototype_name
"Should I setup my table in a different format?"
Yes. Your table might look as follows:
ID Prototype_Code Prototype
------------------------------
1 A Fast381A
1 B Blue4812
1 C Green7181
1 D White4812
2 A Slow841C
2 B Orange8312
3 A Plane281K

export phpList subscribers via sql in mysql database

For some reason, I am unable to export a table of subscribers from my phpList (ver. 3.0.6) admin pages. I've searched on the web, and several others have had this problem but no workarounds have been posted. As a workaround, I would like to query the mySQL database directly to retrieve a similar table of subscribers. But I need help with the SQL command. Note that I don't want to export or backup the mySQL database, I want to query it in the same way that the "export subscribers" button is supposed to do in the phpList admin pages.
In brief, I have two tables to query. The first table, user contains an ID and email for every subscriber. For example:
id | email
1 | e1#gmail.com
2 | e2#gmail.com
The second table, user_attribute contains a userid, attributeid, and value. Note in the example below that userid 1 has values for all three possible attributes, while userid's 2 and 3 are either missing one or more of the three attributeid's, or have blank values for some.
userid | attributeid | value
1 | 1 | 1
1 | 2 | 4
1 | 3 | 6
2 | 1 | 3
2 | 3 |
3 | 1 | 4
I would like to execute a SQL statement that would produce a row of output for each id/email that would look like this (using id 3 as an example):
id | email | attribute1 | attribute2 | attribute3
3 | e3#gmail.com | 4 | "" | "" |
Can someone suggest SQL query language that could accomplish this task?
A related query I would like to run is to find all id/email that do not have a value for attribute3. In the example above, this would be id's 2 and 3. Note that id 3 does not even have a blank value for attributeid3, it is simply missing.
Any help would be appreciated.
John
I know this is a very old post, but I just had to do the same thing. Here's the query I used. Note that you'll need to modify the query based on the custom attributes you have setup. You can see I had name, city and state as shown in the AS clauses below. You'll need to map those to the attribute id. Also, the state has a table of state names that I linked to. I excluded blacklisted (unsubscribed), more than 2 bounces and unconfirmed users.
SELECT
users.email,
(SELECT value
FROM `phplist_user_user_attribute` attrs
WHERE
attrs.userid = users.id and
attributeid=1
) AS name,
(SELECT value
FROM `phplist_user_user_attribute` attrs
WHERE
attrs.userid = users.id and
attributeid=3
) AS city,
(SELECT st.name
FROM `phplist_user_user_attribute` attrs
LEFT JOIN `phplist_listattr_state` st
ON attrs.value = st.id
WHERE
attrs.userid = users.id and
attributeid=4
) AS state
FROM
`phplist_user_user` users
WHERE
users.blacklisted=0 and
users.bouncecount<3 and
users.confirmed=1
;
I hope someone finds this helpful.