In mySQL I have a table:
id
name
code1
code2
code3
1
Jim
aaa
aaa
a
2
Ryan
bb
bbb
b
3
Ted
c
c
cc
expected output:
id
name
concat_code
1
Jim
aaa/a
2
Ryan
bb/bbb/b
3
Ted
c/cc
I tried the below query:
select
id,
name,
concat_ws("/",NULLIF(code1,""),NULLIF(code2,""),NULLIF(code3,"")) as concat_code
from
table1
group by id
But it gives wrong output:
id
name
concat_code
1
Jim
aaa/aaa/a
2
Ryan
bb/bbb/b
3
Ted
c/c/cc
How can I use the distinct combination inside concat_ws()?
This is one example of why having columns foo1, foo2, etc is bad database design; there should be a separate table in a one to many relationship with the original table with one foo value in each row. As is, you have to basically emulate that with unions:
select id, name, group_concat(distinct codes.code separator '/')
from table1
join (
select id,NULLIF(code1,"") as code from table1
union all
select id,NULLIF(code2,"") from table1
union all
select id,NULLIF(code3,"") from table1
) codes using (id)
group by id
or use a convoluted expression for code2, code3, etc that returns null if the code matches any of the previous codes in your concat_ws call.
Bit late, but for other people googling: try:
SELECT id, name,
CONCAT_WS("/",
NULLIF(code1,""),
CASE WHEN code2 NOT IN ('', code1) THEN code2 END,
CASE WHEN code3 NOT IN ('', code1, code2) THEN code3 END
) AS concat_code
FROM table1
The CASE is functioning as a NULLIF with multiple string values, some being the previous values to prevent duplicates.
I left out the GROUP BY id since id seems to be the primary key, that makes that statement useless.
Related
I have 2 tables: one table with many rows and a second table with one row. The tables have no fields in common. Is it possible to combine them into one table with many rows?
I've checked UNION, but MSDN says:
The following are basic rules for combining the result sets of two queries by using UNION:
Each SELECT statement within UNION must have the same number of columns.
The columns must also have similar data types.
The columns in each SELECT statement must also be in the same order.
Example
This is what my tables look like right now:
Table 1 Table 2
Column1 Column2 Column4 Column5 Column3
------- ------- ------- ------- -------
A 1 E 10 a
B 2
C 3
D 4
And this is what I'm trying to achieve as a result:
CONSOLIDATED_Table 3
Column1 Column2 Column3 Column4 Column5
------- ------- ------- ------- -------
A 1 E 10 a
B 2 E 10 a
C 3 E 10 a
D 4 E 10 a
You can add additional columns like this:
select tid, t_name, null as s_name
from teachers t
union all
select sid, null, s_name
from students s;
yes definitely you can use INNER JOIN . its a easy way to get data from multiple table. either you can use sub query and get data in Row format
We use joins to combine columns of multiple tables, whereas we use Union to join rows of multiple tables given that the columns types and nber of columns are the same in all the select queries with union.
Since you want to show all the rows, we can use Union.
Select tid as id, t_name as name from teachers
union all
Select sid as id, s_name as name from students;
Teachers and students
select * from (
select 'teacher' as rowtype, tid as id , t_name as name
from teachers
union all
select 'student', sid, s_name
from students) t
order by name;
This approach produces a cartesian product, but since you have only 1 row in table 2, it should work for your specific use case.
select * from table_1, table_2;
I would like to have rows like a single table like the following
id name parentId
My current tables are (keys between them are foreign keys)
category
id name
which is the parent of all
and
subcategory
id name catId
and the last table which is activity
activity
id name subcatId
For the parentId of category table, it would be nothing as category is the parent of all
My attempt so far have been unsuccessful
Sample Data
category
C-1 HR null
C-2 Development null
subcategory
SC-1 Hiring C-1
SC-2 Admin C-1
SC-3 Developer C-2
activity
A-1 College Hiring SC-1
A-2 Job Fair SC-1
A-3 Java Development SC-3
Result Needed
1 HR null
2 Development null
3 Hiring C-1
4 Admin C-1
5 Developer C-2
6 College SC-1
7 Job Fair SC-1
8 Java Development SC-3
I hope it is clearer. If you need any further information, please let me know
Thanks
my attempt on 2 tables
select name
from (
select c.name
from category c
union all
select b.name
from subcategory b
inner join category ca
on ca.id = b.parentId
)
I get an error saying
Every derived table must have its own alias
Do I need to add the following lines to my query
start with parent_id is null
connect by prior id = parent_id
Try something like this:
SELECT #id := #id + 1 AS id, name, parent_id
FROM ( SELECT name, NULL AS parent_id FROM category
UNION ALL
SELECT id, name, catId FROM subcategory
UNION ALL
SELECT id, name, parentId FROM activity
) q,
( SELECT #id := 0 ) w;
Used UNION ALL to concatenate the results from multiple queries.
In UNION the column names of the first query is used as column names of the result set.
Used variable #id and the assignment operator := to generate the calculated values of the column ID.
Be advised: If you use LIMIT or OFFSET, the values of column id would not be coherent.
Actually, like this should solve your problem:
select name
from (
select c.name
from category c
union all
select b.name
from subcategory b
inner join category ca
on ca.id = b.parentId
) A -- alias is required for sub-query.
You can set anything as alias provided that it won't conflict with some of MySQL reserved word. You can set like this as well ) AS A.
For you situation, I don't think it's necessary to do sub-query or inner join. If you really want the result to be like that you can just use union all:
SELECT name,'' as ID from category
UNION ALL
SELECT name,catId FROM subcategory
UNION ALL
SELECT name,subcatId FROM activity;
I'm trying to phrase this to be as clear as possible.
Here is my scenario : I have two data sets.
Dataset1:
Individual_id
Code 1
Dataset2 :
Individual_id
Code 2
The values in individual_ID are unique to each dataset, meaning that neither list has a duplicated individual_id so a typical join isnt possible (I dont think so anyways)
What I need my final dataset to look like is this:
Individual_ID Code1 Code 2
Any help?
Thanks!
Use UNION ALL :
SELECT Individual_id, Code1, NULL Code2 FROM dataset1
UNION ALL
SELECT Individual_id, NULL, Code2 FROM dataset2
UNION ALL combines the recordsets returns by both queries. Both resultset must return the same columns, so you need to want to the unavailable column in each resultset with NULL.
you can only make cross-join if datasets does not have relationship between them
selec t1.individual_id, Code1, Code2
from t1
cross join t2
but please note that cross-join multiplies results by m x n where m is number of records returned from t1 and n is number of records returned from t2
or
if your intention is to merge two datasets into one then,
select Individual_id, Max(Code1) Code1, Max(Code2) Code2 From
(
SELECT Individual_id, Code1, NULL Code2 FROM dataset1
UNION ALL
SELECT Individual_id, NULL, Code2 FROM dataset2
) t
Group by Individual_id
I use mysql db engine, I wonder is it possible that the data in the table one row transferred to another table, this table would consist of two columns, id and value
each of the transferred value would go into one row and row would look like ID, value, and for as long as it has a value that is transferred to new row maintains the id as long as it has a value that belonged to the id of a row from which it transferred
Initial table looks like
id |country_name |city_1 |city_2 |city_3 |city_4
------------------------------------------------------------------------
1 |Some_country |some_city1 |some_city2 |some_city3 |some_city4
Wanted table looks like
id | city_name
1 | some_city1
1 | some_city2
1 | some_city3
1 | some_city4
Use this for one particular ID
select id, city_name from(
select id, city_1 as city_name from yourTable
union all
select id, city_2 from yourTable
union all
select id, city_3 from yourTable
union all
select id, city_4 from yourTable
) as t where id= yourID
http://sqlfiddle.com/#!9/7ee1f/1
Use this for whole table
select id, city_name from(
select id, city_1 as city_name from yourTable
union all
select id, city_2 from yourTable
union all
select id, city_3 from yourTable
union all
select id, city_4 from yourTable
) as t
order by id
What you are looking for is often referred to as vertical pivoting: you want to pivot something like an array of four city names - hard-wired into the table definition - into four vertical rows.
The solution is a cross join with a temporary table with as many consecutive integers, starting from 1, as you have columns to pivot, in conjunction with a CASE-WHEN expression that makes use of that series of integers.
See here:
WITH foo(id,country_name,city_1,city_2,city_3,city_4) AS (
SELECT 1,'Some_country','some_city1','some_city2','some_city3','some_city4'
)
, four_indexes(idx) AS (
SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
)
SELECT
id AS country_id
, idx AS city_id
, CASE idx
WHEN 1 THEN city_1
WHEN 2 THEN city_2
WHEN 3 THEN city_3
WHEN 4 THEN city_4
ELSE ''
END AS city_name
FROM foo CROSS JOIN four_indexes
;
country_id|city_id|city_name
1| 1|some_city1
1| 3|some_city3
1| 2|some_city2
1| 4|some_city4
Only the other day, I answered a question that was looking for reversing the operation we are performing here: horizontal pivoting.
See here if you're curious ...
How to go about a column with different values in a same row in sql?
Happy Playing -
Marco the Sane
enter code here
Lets say i have the following table:
ID Name ID2 ID3 ID4 ID100
1 Smith 2 3 4 100
20 Joe 10 20 30 200
30 Jane 40 50 60 300
How can i write a statement that goes thru columns ID2 - ID100 one at a time and take the values from the column and the Name column and adds a new row to the table?
To look like so:
ID Name ID2 ID3 ID4 ID100
1 Smith 2 3 4 100
2 Smith
3 Smith
4 Smith
100 Smith
Ive done this, but done want to write 100 select lines.
INSERT INTO mytable
(ID, Name)
SELECT ID2, Name FROM mytable WHERE Name = 'Smith'
UNION ALL
SELECT ID3, Name FROM mytable WHERE Name = 'Smith'
UNION ALL
SELECT ID4, Name FROM mytable WHERE Name = 'Smith';
Your database violates First Normal Form by creating repeating groups. An RDBMS is not designed to handle this design cleanly. This is precisely why you don't want to create repeating groups. Any solution other than redesign will be ugly and slow.
The answer, if redesign isn't an option, is to do the painful part once and then not need do it again.
Create the following view:
CREATE VIEW MyUglyTable_Unpivot (ID, Name, Field_ID, Field_Value) AS
SELECT ID, Name, 'ID2', ID2 FROM MyTable WHERE ID2 IS NOT NULL UNION ALL
SELECT ID, Name, 'ID3', ID3 FROM MyTable WHERE ID3 IS NOT NULL UNION ALL
SELECT ID, Name, 'ID4', ID4 FROM MyTable WHERE ID4 IS NOT NULL UNION ALL
SELECT ID, Name, 'ID5', ID5 FROM MyTable WHERE ID5 IS NOT NULL UNION ALL
SELECT ID, Name, 'ID6', ID6 FROM MyTable WHERE ID6 IS NOT NULL UNION ALL
SELECT ID, Name, 'ID7', ID7 FROM MyTable WHERE ID7 IS NOT NULL UNION ALL
SELECT ID, Name, 'ID8', ID8 FROM MyTable WHERE ID8 IS NOT NULL UNION ALL
SELECT ID, Name, 'ID9', ID9 FROM MyTable WHERE ID9 IS NOT NULL UNION ALL
...
SELECT ID, Name, 'ID99', ID99 FROM MyTable WHERE ID99 IS NOT NULL UNION ALL
SELECT ID, Name, 'ID100', ID100 FROM MyTable WHERE ID100 IS NOT NULL
Obviously, you can pick more sensible names for the view and the fields. You can leave out the WHERE XXXX IS NOT NULL if the underlying table has NOT NULL constraints on those fields, but in my experience they don't. You could also leave it out if you know you really need explicit NULL values, but that's generally considered poor design. NULL is too ambiguous.
The view will be slow as hell, but it will let you do operations like this more easily. If you're able to redesign your system to not use repeating groups, I strongly encourage you to do so.
Now you can do this:
INSERT INTO MyTable (ID, Name)
SELECT Field_Value, Name FROM MyUglyTable_Unpivot
WHERE Name = 'Smith'
Although, I'm thinking you need to have Field_ID in MyTable somewhere to make sense of it all.
its possible if you use foreign key concept otherwise use excel to write those select