Mysql collapse/merge rows - mysql

I have a table with data that looks like this:
ID Name Field2 Field3
1 Steve Value1 <null>
1 Steve <null> Value2
How do I merge these rows into one row that looks like this:
1 Steve Value1 Value2
The row count for ID/Name might vary.

select id, name, max(field2), max(field3)
from your_table
group by id, name

Related

Order by multiple columns with

I'm trying to sort a table by multiple columns, but I should shift the most important column.
Given a sample like:
Name Col1 Col2 Col3
Paul 1 2 1
John 1 1 1
Greg NULL 2 1
Jane 2 2 1
I would like the data to be sorted like John, Paul, Greg and Jane.
If I do ORDER BY Col1, Col2, Col3, Greg is the first result because of NULL.
What I'm trying to do is to "shift" the columns, to discard all the NULL values
Edited:
The desired result is
John
Paul
Greg
Jane
Greg ends up third because the query should remove the null value, working on a "fixed" version like
Name Col1 Col2 Col3
Paul 1 2 1
John 1 1 1
Greg 2 1 - <== Greg cols moved to the left by one step
Jane 2 2 1
Edit2:
I think that something like the COALESCE function should help.
If I run:
SELECT Name, COALESCE(Col1, Col2, Col3, 0) FROM Table1
The result is:
Paul 1
John 1
Greg 2
Jane 2
You Need to derive a new column as per the required order using case statement and use that column to sort the result like below.
select Name,col1,col2,col3
from(
Select *,case when Name='John' then 1
when Name='paul' then 2
when Name= 'Greg' then 3
when Name = 'Jane' then 4
else 5
end as sortid
from test
) a
order by sortid, Name
Use CASE expressions in the ORDER BY clause to check whether a column is null and needs to be shifted:
SELECT *
FROM tablename
ORDER BY COALESCE(Col1, Col2, Col3),
CASE
WHEN Col1 IS NOT NULL THEN COALESCE(Col2, Col3)
WHEN Col2 IS NOT NULL THEN Col3
END,
CASE WHEN Col1 IS NOT NULL AND Col2 IS NOT NULL THEN Col3 END;
See the demo.

What is the best way for selecting 2 row from table in one row?

I have a table like following
TABLE_A
ID PERSON_ID NAME GRADE
---------- ---------- ---------- ----------
1 1 NAME_1 10
2 1 NAME_1 20
3 2 NAME_2 30
4 2 NAME_2 40
...
in this table, for each name there is exactly two rows (two grades).
I want to make a query which results like following
RESULT
PERSON_ID NAME GRADE1 GRADE_2
---------- ---------- ---------- ----------
1 NAME_1 10 20
2 NAME_2 30 40
What is the best way for this.
I can use self join but I think this is not correct method
You can use GROUP BY as the other person suggested.
Or you can make a join.
select t1.person_id, t1.grade as grade1, t2.grade as grade2
from TABLE_A t1 join TABLE_A t2 on t1.person_id=t2.person_id and t1.id!=t2.id
This JOIN joins all the rows with the same person, but not the rows with the same id so you filter out the duplicates.
If you are using MySQL, and if all names have exactly two records, and the first grade is the one with the lower id and the second grade the other, then you could use a query like this one:
select
person_id,
name,
group_concat(grade order by id) as grades
from
table_a
group by
person_id,
name
then if you want to separate grades into two new columns you could use SUBSTRING_INDEX:
select
person_id,
name,
substring_index(group_concat(grade order by id), ',', 1) as grade1,
substring_index(group_concat(grade order by id), ',', -1) as grade2
from
table_a
group by
person_id,
name
Try this for SQL SERVER
; WITH CTE AS(
SELECT PERSON_ID, NAME, GRADE AS GRADE_1,
LEAD(GRADE) OVER(PARTITION BY NAME ORDER BY NAME) AS GRADE_2
FROM TABLE_A
)
SELECT * FROM CTE
WHERE GRADE_2 IS NOT NULL
RESULT SET:
PERSON_ID NAME GRADE_1 GRADE_2
---------- ---------- ---------- ----------
1 NAME_1 10 20
2 NAME_2 30 40
As soon as the topic starter didn't mention the ORDER of grades and "there is exactly two rows (two grades)" I think the easiest way:
SELECT PERSON_ID,
MAX(NAME) as NAME,
MIN(GRADE) as GRADE1,
MAX(GRADE) as GRADE2
FROM TABLE_A
GROUP BY PERSON_ID
I found best answer for PostgreSQL in this link
https://www.postgresql.org/docs/9.2/static/tablefunc.html
In PostgreSQL there is the crosstab(text) function.
The crosstab function is used to produce "pivot" displays, wherein data is listed across the page rather than down. For example, we might have data like
row1 val11
row1 val12
row1 val13
...
row2 val21
row2 val22
row2 val23
...
which we wish to display like
row1 val11 val12 val13 ...
row2 val21 val22 val23 ...
...
The crosstab function takes a text parameter that is a SQL query producing raw data formatted in the first way, and produces a table formatted in the second way.
The sql parameter is a SQL statement that produces the source set of data.
This statement must return one row_name column, one category column, and one value column. N is an obsolete parameter, ignored if supplied (formerly this had to match the number of output value columns, but now that is determined by the calling query).
For example, the provided query might produce a set something like:
row_name cat value
----------+-------+-------
row1 cat1 val1
row1 cat2 val2
row1 cat3 val3
row1 cat4 val4
row2 cat1 val5
row2 cat2 val6
row2 cat3 val7
row2 cat4 val8
The crosstab function is declared to return setof record, so the actual names and types of the output columns must be defined in the FROM clause of the calling SELECT statement, for example:
SELECT * FROM crosstab('...') AS ct(row_name text, category_1 text, category_2 text);
This example produces a set something like:
<== value columns ==>
row_name category_1 category_2
----------+------------+------------
row1 val1 val2
row2 val5 val6
For more read section F.35.1.2. in URL entered top of the answer

MySQL : How to know which table that record belongs to in UNION result

Lets say that I want to get the records from 2 table by using UNION.
How could I add a field to each record that would tell me which table it belongs to? It just something like this :
id | title | link | table
-----------------------------------------------------
1 | Title 1 | somelink.html | articles1
2 | Title 2 | link2 .html | articles2
3 | Title 3 | link3 .html | articles1
Thanks in advance?
select some_column, 'union_1' as from_where
from table1
union
select some_column, 'union_2' as from_where
from table2
You could try something like
SELECT Col1, Col2, 'Table1' TableSource
FROm Table1
UNION ALL
SELECT Col1, Col2, 'Table2' TableSource
FROm Table2
This will work/make sense for UNION ALL, but might be misleading if you use UNION, as duplicates will then be included due to the differentiating source column.
Just put it in your UNION, like:
SELECT *, 'articles1' AS table_name FROM articles1
UNION ALL
SELECT *, 'articles2' AS table_name FROM articles2

SQL query to create many-to-one tables from one table?

I have a table like so:
column1 column2
------- -------
key1 value1
key1 value2
key1 value3
key2 value4
key2 value5
key2 value6
I would like to create the following two tables:
id column1
-- -------
1 key1
2 key2
key_id column2
------ -------
1 value1
1 value2
1 value3
2 value4
2 value5
2 value6
That is, I would like to split a table into a many-to-one relation between two new tables.
How would I write an SQL query to do this?
Assuming the id column in your first new table is an identity column:
INSERT INTO NewTable1
(column1)
SELECT DISTINCT column1
FROM OldTable;
INSERT INTO NewTable2
(key_id, column2)
SELECT n1.id, o.column2
FROM OldTable o
INNER JOIN NewTable1 n1
ON o.column1 = n1.column1;
Why don’t u use php my admin and enter the data manually. It will write the php for you.
Also your id field on each table must always be unique and auto incremented.
you cannot use 111 222 in a primary key

How to retrieve distinct values from more than one column?

I have two columns of data. I'd like to run select statement on them that grabs all the distinct pieces of data in these columns 1 time. For instance.
*column 1* *column 2*
dog monkey
monkey elephant
dog monkey
I wanna be able to returna result set that has dog, monkey and elephant in it and that's all.
You can use two selects:
Select column1 As c From t
Union
Select column2 From t
Union will take care of duplicates:
The default behavior for UNION is that duplicate rows are removed from the result.
What about the following?
SELECT column1 unique_data FROM your_table
UNION
SELECT column2 unique_data FROM your_table;
Test case:
CREATE TABLE your_table (column1 varchar(50), column2 varchar(50));
INSERT INTO your_table VALUES ('dog', 'monkey');
INSERT INTO your_table VALUES ('monkey', 'elephant');
INSERT INTO your_table VALUES ('dog', 'monkey');
Result:
+-------------+
| unique_data |
+-------------+
| dog |
| monkey |
| elephant |
+-------------+
3 rows in set (0.00 sec)
It may be lil dumb: select distinct from (select distinct from first_column union select distinct from second) - not valid sql, just logic
Use UNION, sample:
select
column_1 as name
from Table_1
union
select
column_2 as name
from Table_1
Output:
dog
elephant
monkey