mysql Select values from multiple columns into single column - mysql

I have a table in a database that has several columns containing the same sort of data, these values are allowed to be null. I need to select each of the non-null values into a single column of values that care about the identity of the row from which they originated.
So, for a table that looks like this:
+---------+------+--------+------+
| Id | name | v1 | v2 |
+---------+------+--------+------+
| 1 | eko | aa | bb |
| 2 | agus | null | cc |
| 3 | eko | dd | null|
| 4 | budi | aa | null|
| 5 | siti | ff | gg |
+---------+------+--------+------+
I wish to select each of the values aa,bb,cc, etc into a single column. My result data should look like the following table.
+-------+-------+-------+
| id | name | v |
+-------+-------+-------+
| 1 | eko | aa |
| 1 | eko | bb |
| 2 | agus | cc |
| 3 | eko | dd |
| 4 | budi | aa |
| 5 | siti | ff |
| 5 | siti | gg |
+-------+-------+-------+
I am using mysql. Is there a technique for achieving this with respect to performance too?

You could just use two queries and use the union statement of the two to append the two sets:
Select id, v1 as v
From table
where v1 is not null
union all
select id, v2 as v
from table
where v2 is not null
But to make this dynamic (any number of v...) you would have to iterate over the columns. See:mysql, iterate through column names

Related

How to compare two pairs from one table to two pairs from another table on MySQL

I want to compare both values from the following tables.
Arlarp
+------+--------+
|ARLID | ARPID |
+------+--------+
| AA | AIA |
| OA | AIA |
| AA | ATL |
| AA | DFW |
| AA | LAX |
| DL | ORD |
| EK | ORD |
| AC | YYZ |
+------+--------+
Flight
+------+---------+----------+
| ARLID| ARPID_1 | ARPID_2 |
+------+---------+----------+
| AA | ATL | DFW |
| AA | DFW | ATL |
| UA | ORD | DFW |
+------+---------+----------+
From Arlarp, we have existing pairs of values. I want to find the missing pairs of values of Arlarp from Flight that don't exist in Flight when comparing flight's ARLID with ARPID_1 and ARPID_2.
This is what the result should be:
+------+---------+
| ARLID| ARPID |
+------+---------+
| UA | ORD |
+------+---------+
| UA | DFA |
+------+---------+
One option is to unpivot the flight table with union all, and then pull out rows that do not exist in alarp with not exists:
select f.*
from (
select arlid, arpid_1 arpid from flight
union all select arlid, arpid_2 from flight
) f
where not exists (select 1 from alarp a where a.arlid = f.arlid and a.arpid = f.arpd)

how to group selection from other table as one column in sql?

here is two tables:
a:
+-----+------------------------+
| id | conten |
+-----+------------------------+
| 1 | q. |
| 2 | q. |
| 3 | s. |
| 4 | g |
| 1 | a |
| 2 | a |
+-----+------------------------+
b:
+-----+------------------------+
| id | type |
+-----+------------------------+
| 1 | I. |
| 2 | II. |
| 3 | III. |
| 4 | IV |
| 5 | V |
| 6 | VI |
+-----+------------------------+
Is there a way to select from a and b so that for one id 2, there will be one additional field that groups all content from that id? the select result should be something like this:
+-----+------------------------+-----------+
| id | type | contents |
+-----+------------------------+-----------+
| 2 |I. | q,a |
+-----+------------------------+-----------+
Edited
btw, if there is a way to do it by sqlahcmey, that would be sweet.
SELECT b.id, b.type, IFNULL(GROUP_CONCAT(a.conten), '') AS contents
FROM b
LEFT JOIN a ON a.id = b.id
GROUP BY b.id
See How do I write a group_concat function in sqlalchemy? for how to translate GROUP_CONCAT to SQLAlchemy.

MySQL update table from a EAV table using case when

I have a EAV table. I want to convert this into a normal table in a single query. How can I do this?
Table A
| ID | Entity | Attribute |
+----+--------+-----------+
| 1 | AA | 5 |
| 2 | AA | 2 |
| 3 | AA | 4 |
| 1 | BB | 6 |
| 2 | BB | 5 |
Table B (intended. This has only ID as of now)
| ID | AA | BB |
+----+-----+------+
| 1 | 5 | 6 |
| 2 | 2 | 5 |
| 3 | 4 | NULL |
I tried the following:
update B join A using(ID) set b.AA=(case when Entity='AA' then Attribute end),b.BB=(case when Entity='BB' then Attribute end);
update B join A using(ID) set b.AA=(case when Entity='AA' then Attribute else AA end),b.BB=(case when Entity='BB' then Attribute else BB end);
But the table is not getting updated. Both the fields are set to NULL for all the IDs. I can write separate update queries for each Entity, but I have >100 different entities and each query takes hours to run (I have many records).

Joining 3 tables from two different Databases?

Database 1 (2 tables) : sandbox_maesc4
table 1: coordinates
+----------------------------------------+
|coord_id | section_name | station_number|
+----------------------------------------+
| 1 | A | A7 |
| 2 | B | B20 |
| 3 | C | C3 |
| 4 | D | D14 |
| 5 | E | E9 |
+----------------------------------------+
table 2: workstation_userlogged
+----------------------------------+
| id | ws | user |
+----------------------------------+
| 1 | COMP123 | ryan |
| 2 | COMP345 | luda |
| 3 | COMP567 | chris |
| 4 | COMP891 | michel|
| 5 | COMP444 | isabel|
+----------------------------------+
Database 2 (1 table): softphone_materials_updater
Table 1: workstation
+----------------------------+
| ID | ws | pod |
+----------------------------+
| 1 | COMP123 | A07 |
| 2 | COMP345 | B20 |
| 3 | COMP567 | C03 |
| 4 | COMP891 | D14 |
| 5 | COMP444 | E09 |
+----------------------------+
Problem:
I only have read access in Database 2.
So I did a SELECT query for both fields and created the table "userlogged".
Now, I want to combine both tables "coordinates" and "userlogged" by joining table "workstation"
with their relation of the "station_number" field and "pod" field from. How can I achieve this? Below is the query that I tried but doesnt work.
I have extra fields in "coordinates" table (X,Y fields with actual coordinates). In PHP I use all fields to show them on screen.
SELECT
coordinate_id,
section_name,
x_coord,
y_coord,
ws.username,
ws.hostname,
w.pod,
FROM
sandbox_maesc4.coordinates c,
sandbox_maesc4.workstation_userlogged ws
INNER JOIN
softphone_materials_updater.workstations w
ON c.station_number = w.pod
I think maybe this is what you want?
SELECT
coordinate_id,
section_name,
x_coord,
y_coord,
wsu.username,
wsu.hostname,
w.pod
FROM
sandbox_maesc4.coordinates c
INNER JOIN
softphone_materials_updater.workstations w
ON c.station_number = w.pod
INNER JOIN
sandbox_maesc4.workstation_userlogged wsu
ON w.ws = wsu.ws
Not sure about the database and table names, they seem to differ between your sample query and the description.

SQL Query design involving multiple tables

I am working on a MYSQL query design that, in my opinion, is pretty hard. I'm not experienced in SQL, so I found it really dificult. The point is:
I've got the 'ordertable' table which stores the order of some codes (AA, BB, CC..). In another table, 'AllTables' I store the name of a table associated to a code (AA -> tableA). Finally, 'tableA' table stores some data of diferent units (unit1, unit2...).
CASE 1.
ordertable : Order of codes is given like:
+----------------+------+
| split_position | code |
+----------------+------+
| 1 | AA |
| 2 | BB |
| 3 | CC |
| 4 | DD |
+----------------+------+
CASE 2.
ordertable Order of codes is given like:
+-------+------+------+------+------+
| id | pos1 | pos2 | pos3 | pos4 |
+-------+------+------+------+------+
| unit1 | AA | BB | DD | CC |
| unit2 | CC | BB | AA | DD |
| unit3 | BB | DD | CC | AA |
+-------+------+------+------+------+
In Case 2 we can also find special codes like 'var15':
+-------+------+-------+------+-------+
| id | pos1 | pos2 | pos3 | pos4 |
+-------+------+-------+------+-------+
| unit1 | AA | var15 | DD | var37 |
| unit2 | CC | BB | AA | DD |
+-------+------+-------+------+-------+
In case we find something similar to 'var'+ number the associated table is always the same: 'variable', where de 'id' is the number of the code 'var37' -> id = 37.
variable
+-----+------------+------+--------+
| id | name | time | active |
+-----+------------+------+--------+
| 15 | Pedro | 5 | 1 |
| 17 | Maria | 4 | 1 |
+-----+------------+------+--------+
Info of tables:
AllTables
+------+------------+
| code | name |
+------+------------+
| AA | tableA |
| BB | tableB |
| CC | tableC |
| DD | tableD |
+------+------------+
tableA
+-------+------+------+--------+
| id | name | time | active |
+-------+------+------+--------+
| unit1 | Mark | 11 | 1 |
| unit2 | Jame | 20 | 0 |
+-------+------+------+--------+
tableB
+-------+------+------+--------+
| id | name | time | active |
+-------+------+------+--------+
| unit1 | Mari | 44 | 1 |
| unit3 | nam2 | 57 | 1 |
+-------+------+------+--------+
Given an id='unit1', I'm expecting the next:
Result
+----------------+------+-------+-------+--------+
| split_position | code | name | time | active |
+----------------+------+-------+-------+--------+
| 1 | AA | Mark | 11 | 1 |
| 2 | BB | Mari | 44 | 1 |
| 3 | CC | | | 0 |
| 4 | DD | | | 0 |
+----------------+------+-------+-------+--------+
In case that the id (unit1) does not exists in tableC or tableD, 'split_position' and 'code' associated should appear but in the 'active' field should appear a 0.
it's a bit of a steep learning curve, but basically you have to declare a cursor and loop
over the each row in the ordertable and select your data then UNION the result together using dynamic SQL.
check this sqlFiddle
to order by final result by split position ASC just add ORDER BY split_position ASC to the sql variable before executing it like this sqlFiddle
to solve your problem you would need something like the following:
select split_position, code, name, time, active
from
(
select 'tableA' as tablename, id, [name], [time], active
from tableA
union all select 'tableB' as tablename, id, [name], [time], active
from tableB
) as tbls
inner join alltables atbls
on tbls.tablename=atbls.name
inner join ordertable ot
on atbls.code=ot.code
where tbls.id='unit1'