How to pivot table in MySql? - mysql

I have a table illustrated on the attached screen:
And data is presented:
As you can see it contains all fields from lines (value, column_id - is field type). Each field has line_index and column_index of position and column_id.
I want to get back all lines with all field names like:
line_index column_id_1 column_name1 column_id_2 column_name2 column_id_3 column_name3
0 1 Age 2 Vasile 3 NY
More simply I need to build all fields(rows) to columns then to lines back.
Should I use Pivot and is it possible in MySQL?
Link to sqlfiddle

You will need to group the results by line_index and conditionally transform rows to columns.
SELECT l.line_index,
MAX(CASE WHEN ct.column_name = "NAME" THEN l.value ELSE NULL END) AS "NAME" ,
MAX(CASE WHEN ct.column_name = "AGE" THEN l.value ELSE NULL END) AS "AGE" ,
MAX(CASE WHEN ct.column_name = "ZUP" THEN l.value ELSE NULL END) AS "ZUP"
FROM columns_types ct
LEFT JOIN `lines` l ON l.column_id = ct.column_id
GROUP BY l.line_index;
Try it here. Also I did some changes in your schema which I felt didn't impact the data stored in the tables. You were adding redundant rows(perhaps) in your columns_types table. And by looking at the query, you know that you will have to build a MAX(CASE statement for each column, so its best if you first fetch it and then build the final query in some programming language.

Related

query multiple filter from a table that data store in single column structure

I have a database that stores all the field data with below structure in single column fieldValue and fieldID.
I would like to know for this type of structure how I can have 2 filters in where condition?
for example how I can query all the fieldID2 which is equal to High and all the fieldID11 which is Discrepancy.
database is mysql.
The output will look like below, the output will be like pivot table. please take note that I dont have any problem for write query, I want to know how to have more than one where condition for two columns.
fieldid1 fieldid2 fieldid3 fieldid4
ahmed high xxxxxssss Finance
I am not sure what you are asking exactly. Anyway, key/value tables are usually queried by aggregation. So if per InternalNo you want to show the values for FieldIDs 1, 2, 3 and 4, provided their value for FieldID 2 is 'High' and the value for FieldID 11 is 'Discrepancy', you'd do:
select
internalno,
any_value(case when fieldid = 1 then fieldvalue end) as fieldvalue1,
any_value(case when fieldid = 2 then fieldvalue end) as fieldvalue2,
any_value(case when fieldid = 3 then fieldvalue end) as fieldvalue3,
any_value(case when fieldid = 4 then fieldvalue end) as fieldvalue4
from keyvalues
group by internalno
having any_value(case when fieldid = 2 then fieldvalue end) = 'High'
and any_value(case when fieldid = 11 then fieldvalue end) = 'Discrepancy';
In order to speed this up, you can apply a WHERE clause on the desired FieldIDs;
where fieldid in (1,2,3,4,11)
As to multiple values for one attribute like your FieldID 10 for InternalNo 89796, you'd have to decide which value(s) to get and ANY_VALUE might not suffice for that.

MySQL count different value in same table

I am working on a database right now, and I am trying to select some special data.
so the table looks like this.
name title type
Type is including two different value, "book" and "paper".
And this is the result I would like to get
name book paper
person A 0 1
person B 1 2
person C 0 5
What is the best way to write the query it in MySQL.
You may use conditional aggregation:
SELECT
name,
SUM(CASE WHEN type = 'book' THEN 1 ELSE 0 END) AS book,
SUM(CASE WHEN type = 'paper' THEN 1 ELSE 0 END) AS paper
FROM yourTable
GROUP BY
name;

mysql content as column names

I have a table with the contents and columns like in the picture (left side), but I want to display it on my website page with format like in picture (right).
I've tried various combinations of php and mysql syntax but still can not display them.
SELECT DISTINCT
'NAMA',
'TEMPAT LAHIR',
COUNT(PENDIDIKAN) AS Jumlah
FROM
table_name
GROUP BY
'TEMPAT LAHIR'
ORDER BY
NAMA,
'TEMPAT LAHIR'
Try following.
SELECT `TEMPAT LAHIR`,
COUNT(CASE WHEN (PENDIDIKAN = 'S1') THEN PENDIDIKAN ELSE NULL END) AS S1,
COUNT(CASE WHEN (PENDIDIKAN = 'S2') THEN PENDIDIKAN ELSE NULL END) AS S2,
COUNT(CASE WHEN (PENDIDIKAN = 'SMA') THEN PENDIDIKAN ELSE NULL END) AS SMA
FROM `table_name`
GROUP BY `TEMPAT LAHIR`
You don't need 'NAMA' in your query, but you want the 'Jumlah' column. Like this:
SELECT DISTINCT
`TEMPAT LAHIR`,
COUNT(`PENDIDIKAN`) AS `JumlahCount`,
`Jumlah`
FROM
`table_name`
GROUP BY
`TEMPAT LAHIR`
ORDER BY
'TEMPAT LAHIR`
After that a bit of PHP is needed to render it correctly. I know this answer is incomplete, but the same could be said of your question. It was just too long to put in a comment.

SQL where particular column values appears

I wasn't sure how to really search for this..
Lets say I have a simple table like this
ID Type
1 0
1 1
2 1
3 0
4 0
4 1
How could I select all ID's which have a type of both 0 and 1?
SELECT id,type
FROM t
GROUP BY id
HAVING SUM(type=0)>0
AND SUM(type=1)>0
You just group by id ,than with HAVING you use post aggregation filtering to check for 0 and 1.
Having is pretty expensive and that query can't hit keys.
SELECT ID FROM foo AS foo0 JOIN foo AS foo1 USING (ID) WHERE foo0.Type=0 AND foo1.Type=1 GROUP BY foo0.id.
A more generalized way of doing this would by to use a CASE column for each value you need to test combined with a GROUP BY on the id column. This means that if you have n conditions to test for, you would have a column indicating if each condition is met for a given id. Then the HAVING condition becomes trivial and you can use it like any multi-column filter, or use the grouping as your subquery and the code looks simpler and the logic becomes even easier to follow.
SELECT id, Type0,Type1
FROM (
SELECT id,
Type0 = max(CASE WHEN type = 0 THEN TRUE END)
, Type1 = max(CASE WHEN type = 1 THEN TRUE END)
FROM t
GROUP BY id
) pivot
WHERE Type0 = TRUE and Type1 = TRUE

How to transform rows into columns having no column with unique values?

I am trying to transform some rows into columns in MySQL. I know it has been asked and answered previously, like here.
My problem is, there is nothing in my rows on which I can apply the 'if' construct. (At least I think so.)
E.g. For the following input,
2 5 1000
2 6 2000
I can run this query:
INSERT INTO SUMMARY
(user_id,valueA,valueB)
SELECT d.user_id,
MAX(CASE WHEN d.code = 5 THEN d.value ELSE NULL END),
MAX(CASE WHEN d.code = 6 THEN d.value ELSE NULL END),
FROM DETAILS d
GROUP BY d.user_id
and get this output:
2 1000 2000
But my problem is, my input is something like this:
2 6 1000
2 6 2000
(The values in the second column are not unique.)
And i still need the same output, i.e.:
2 1000 2000
Can it be done in MySQL? If yes, can anyone help me with this?
Well, if you don't have any idea of how many columns there will be in your pivot table, nor have a value to decide which value should go in a given column, the best solution I can recommend is to use a GROUP_CONCAT function and then do some parsing in your code:
SELECT d.user_id, GROUP_CONCAT(
d.value SEPARATOR ','
) AS val
FROM details d
GROUP BY d.user_id;