mysql merge rows with no unique rows - mysql

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

Related

Implementing SUMIF() function from Excel to SQL

Lately, I have been learning how to use SQL in order to process data. Normally, I would use Python for that purpose, but SQL is required for the classes and I still very much struggle with using it comfortably in more complicated scenarios.
What I want to achieve is the same result as in the following screenshot in Excel:
Behaviour in Excel, that I want to implement in SQL
The formula I used in Excel:
=SUMIF(B$2:B2;B2;C$2:C2)
Sample of the table:
> select * from orders limit 5;
+------------+---------------+---------+
| ID | clientID | tonnage |
+------------+---------------+---------+
| 2005-01-01 | 872-13-44-365 | 10 |
| 2005-01-04 | 369-43-03-176 | 2 |
| 2005-01-05 | 408-24-90-350 | 2 |
| 2005-01-10 | 944-16-93-033 | 5 |
| 2005-01-11 | 645-32-78-780 | 14 |
+------------+---------------+---------+
The implementation is supposed to return similar results as following group by query:
select
orders.clientID as ID,
sum(orders.tonnage) as Tonnage
from orders
group by orders.clientID;
That is, return how much each client have purchased, but at the same I want it to return each step of the addition as separate record.
For an instance:
Client A bought 350 in the first order and then 231 in the second one. In such case the query would return something like this:
client A - 350 - 350 // first order
client A - 281 - 581 // second order
Example, how it would look like in Excel
I have already tried to use something like:
select
orders.clientID as ID,
sum(case when orders.clientID = <ID> then orders.tonnage end)
from orders;
But got stuck quickly, since I would need to somehow dynamically change this <ID> and store it's value in some kind of temporary variable and I can't really figure out how to implement such thing in SQL.
You can use window function for running sum.
In your case, use like this
select id, clientID, sum(tonnage) over (partition by clientID order by id) tonnageRunning
from orders
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=13a8c2d46b5ac22c5c120ac937bd6e7a

MYSQL, Include Null Results

Want a null row where no data exist
Hello. This is in regards to MySQL Workbench 6.3.
I'm trying to return a list of results for every item listed in my select statement, which would include those items that don't actually exist. So if i list 5 items in my select statement and only 3 exist, i'd like to get 5 rows returned, 3 actual rows with data and 2 more rows that only show null. Can someone please show me how to edit my query below to show this ? Thank you !
select emails from table where email in (dog, frog, cat, tiger, lizard);
Actual Result (only the 3 emails that actual exist show)
dog
cat
tiger
Desired Result
dog
null
cat
tiger
null
The desired results are not possible.. You can't expect MySQL to
return the selected records in the order they went in the IN()
operator.
So i think you better off when you change the desired result to something you know sometiming was not found in the table, i think you are looking for.
Query
SELECT
search_emails.email
, (
CASE
WHEN t.email IS NOT NULL
THEN 'true' ELSE 'false'
END
) AS found
FROM (
SELECT 'dog' AS email
UNION
SELECT 'frog' AS email
UNION
SELECT 'cat' AS email
UNION
SELECT 'tiger' AS email
UNION
SELECT 'lizard' AS email
) AS search_emails
LEFT JOIN
t
ON
t.email = search_emails.email
Result
| email | found |
| ------ | ----- |
| dog | true |
| cat | true |
| tiger | true |
| frog | false |
| lizard | false |
see demo
select emails from table where email in (dog, frog, cat, tiger, lizard) OR email IS NULL
be sure that the values provided for IN (...) are provided as strings.

SQLYOG - SQL - Merging two columns into 1 column

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.

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.

MySQL - get unique id across multiple rows and 2 columns - GROUP BY almost gets me there

I need a way to search across dynamically generated fields. A user will search for 3 required fields and n number of optional fields.
This is for search functionality.
Said user might want to look for any issue that is on the West elevation (field_id->1, field_value->West), on the 6th Floor (field_id->4, field_value->6), and in room #52 (field_id->2, field_value-> 52).
Here is what I have so far:
$query = "SELECT inspection_finding_id
FROM if_field_values
WHERE field_id IN (1, 2, 4) AND field_value IN ('West', 6, 52)
GROUP BY field_id, field_value, inspection_finding_id";
$result = mysql_query($query);
I only need the id's that match ALL of the criteria... With the above I get some orphan records that are also contain data on the 6th floor.
I dont have enought rep to show an image of my table so here is a sad attempt to display my table
| id | field_id | field_value |
+----+----------+-------------+
|161 | 1 | West |
|161 | 4 | 6 |
|161 | 2 | 52 |
|163 | 4 | 6 |
A general solution for finding entities satisfying all attribute conditions in EAV model is to separate all conditions by OR, GROUP BY entity and filter results with HAVING count(*) equal to number of conditions.
SELECT inspection_finding_id
FROM if_field_values
WHERE field_id = 1 AND field_value = 'West'
OR field_id = 4 AND field_value = '6'
OR field_id = 2 AND field_value = '52'
GROUP BY inspection_finding_id
HAVING COUNT(DISTINCT field_id) = 3;
You need to join the table with itself, a similar problem to yours is archived.
If you're trying to use IN you'll get multiple rows that you'll need to count afterwards to see if they match and it'll be a mess with your optional fields.